如何在不调用成员函数的情况下向C++对象传递模板参数?
能否直接向对象传递模板参数,而非仅传递给成员函数?
我可以向对象的成员函数传递模板参数,但无法直接传递给对象本身,这是否可行?我希望实现的效果是让log<2>与log.Tag<2>的行为完全一致。
以下是我的代码:
#include <iostream> #include <string> using namespace std; class Logger { public: Logger& operator()(int t) { cerr << "(tag " << t << ") "; return *this; } Logger& operator<<(const string &s) { cerr << s << endl; return *this; } template<int t> Logger& Tag() { cerr << "(tag " << t << ") "; return *this; } Logger() {} template<int t> Logger() { cerr << "(tag " << t << ") "; } }; int main() { { Logger log; log(2) << "World"; log(3) << "World"; log.Tag<2>() << "Template 1"; log<2> << "Template 2"; // <-- error } }
GCC 13.2的错误信息:
error: invalid operands to binary expression ('Logger' and 'int') log<2> << "Template 2"; ~~~^~
问题原因
编译器将log<2>解析成了小于运算符表达式(log < 2),而非你期望的“向对象传递模板参数”。这是因为:
<>语法仅能用于模板名(类模板、函数模板、成员模板函数),不能直接用于已实例化的普通对象。- 你的
Logger类并非模板类,log是一个具体的对象实例,编译器无法将log<2>识别为模板参数传递操作。
可行解决方案
直接实现log<2>这种语法在C++中是不允许的,但可以通过以下方式达到等价效果:
继续使用成员模板函数(推荐)
你已经实现的log.Tag<2>()是完全符合C++语法的标准写法,无需额外改动,行为和你期望的完全一致。重载模板版
operator()(可选)
如果想要更贴近函数调用的写法,可以添加一个接收编译期常量的模板版operator():
#include <type_traits> // 需要包含这个头文件 // 在Logger类中添加 template<int t> Logger& operator()(std::integral_constant<int, t>) { cerr << "(tag " << t << ") "; return *this; }
调用方式:
log(std::integral_constant<int, 2>{}) << "Template 2";
不过这种写法比Tag<2>()更冗长,实用性不如前者。
- 将Logger改为模板类(不推荐,不符合原有需求)
如果允许每个标签对应不同的Logger类型,可以将类改为模板:
template<int Tag = 0> class Logger { public: Logger() { if constexpr (Tag != 0) { cerr << "(tag " << Tag << ") "; } } template<int t> Logger<t> tag() { return Logger<t>{}; } Logger& operator<<(const string& s) { cerr << s << endl; return *this; } };
调用方式:
Logger<> log; log.tag<2>() << "Template 2";
但这种方式会创建新的Logger<2>对象,和你原有代码中复用同一个log对象的逻辑不符。
内容的提问来源于stack exchange,提问作者Pietro
相关产品推荐
相关产品推荐

