如何在不知道 class 是否为模板的情况下调用模板化成员函数?
How do I call a templated member function without knowing whether or not the class is a template?
假设我有以下宏:
#define CALL_FOO(x) x.foo<int>();
这个宏将调用带有模板参数 int
的模板化 foo
函数,只要 x
本身不是模板类型,它就会编译。如果是,我需要定义该宏的第二个变体来处理模板类型:
#define CALL_FOO_TEMPLATED(x) x.template foo<int>();
我如何创建一个宏来调用模板成员函数 foo
而不管 x
是否是从属名称?
(首先,从不 将 ;
放在宏的末尾。它会在某些 if
调用中中断。)
我认为您可以随时安全地将 template
放在 foo
前面。有时它是必需的。有时它是可选的。但我不认为在模板前立即使用 template
是不被允许的。
#define CALL_FOO(x) x.template foo<int>()
您正在寻找的答案,在 [temp.names] 中,需要 template
时:
When the name of a member template specialization appears after .
or ->
in a postfix-expression or after a
nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent
or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of
the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template
.
但是虽然对引用的名称有限制:
A name prefixed by the keyword template
shall be a template-id or the name shall refer to a class template.
其中"dependence-ness"没有任何限制:
[ Note: As is the case with the typename
prefix, the template
prefix is allowed in cases where it is
not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the ->
or .
is not
dependent on a template-parameter, or the use does not appear in the scope of a template. —end note]
所以下面的代码总能正常编译:
struct X
{
template <typename >
void foo() { }
};
int main()
{
X{}.template foo<int >(); // template keyword not strictly necessary
}
真正的答案是:不要为这样的事情使用宏。只需写出函数调用即可。以后大家会感谢你的。额外的好处是在调用站点,您知道是否需要 template
关键字,因此您可以在需要的地方精确使用它。
对于 C++11,只需无条件地使用 template
。对于 C++03,大多数编译器甚至会接受 template
非依赖名称,但可能会发出警告。如果你需要迎合其他编译器,或者警告不可接受,你可以尝试这样:
template<class X>
void CALL_FOO(X& x)
{
x.template foo<int>();
}
template<class X>
void CALL_FOO(const X& x)
{
x.template foo<int>();
}
这不允许您传递 foo
返回的值。如果它是固定类型,则添加起来很容易。否则你需要某种形式的 decltype
,它不是 C++03 的一部分,但你可以尝试 Boost.Typeof.
假设我有以下宏:
#define CALL_FOO(x) x.foo<int>();
这个宏将调用带有模板参数 int
的模板化 foo
函数,只要 x
本身不是模板类型,它就会编译。如果是,我需要定义该宏的第二个变体来处理模板类型:
#define CALL_FOO_TEMPLATED(x) x.template foo<int>();
我如何创建一个宏来调用模板成员函数 foo
而不管 x
是否是从属名称?
(首先,从不 将 ;
放在宏的末尾。它会在某些 if
调用中中断。)
我认为您可以随时安全地将 template
放在 foo
前面。有时它是必需的。有时它是可选的。但我不认为在模板前立即使用 template
是不被允许的。
#define CALL_FOO(x) x.template foo<int>()
您正在寻找的答案,在 [temp.names] 中,需要 template
时:
When the name of a member template specialization appears after
.
or->
in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keywordtemplate
.
但是虽然对引用的名称有限制:
A name prefixed by the keyword
template
shall be a template-id or the name shall refer to a class template.
其中"dependence-ness"没有任何限制:
[ Note: As is the case with the
typename
prefix, thetemplate
prefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the->
or.
is not dependent on a template-parameter, or the use does not appear in the scope of a template. —end note]
所以下面的代码总能正常编译:
struct X
{
template <typename >
void foo() { }
};
int main()
{
X{}.template foo<int >(); // template keyword not strictly necessary
}
真正的答案是:不要为这样的事情使用宏。只需写出函数调用即可。以后大家会感谢你的。额外的好处是在调用站点,您知道是否需要 template
关键字,因此您可以在需要的地方精确使用它。
对于 C++11,只需无条件地使用 template
。对于 C++03,大多数编译器甚至会接受 template
非依赖名称,但可能会发出警告。如果你需要迎合其他编译器,或者警告不可接受,你可以尝试这样:
template<class X>
void CALL_FOO(X& x)
{
x.template foo<int>();
}
template<class X>
void CALL_FOO(const X& x)
{
x.template foo<int>();
}
这不允许您传递 foo
返回的值。如果它是固定类型,则添加起来很容易。否则你需要某种形式的 decltype
,它不是 C++03 的一部分,但你可以尝试 Boost.Typeof.