假设我有以下宏:
foo(bar.toArray(new Bar[bar.size()]));
此宏将使用模板参数#define CALL_FOO(x) x.foo<int>();
调用模板foo
函数,只要int
本身不是模板类型,它就会编译。如果是,我需要定义此宏的第二个变体来处理模板类型:
x
无论#define CALL_FOO_TEMPLATED(x) x.template foo<int>();
是否为从属名称,如何创建将调用模板成员函数foo
的宏?
答案 0 :(得分:6)
在以下情况下,您需要[temp.names],GET /attractions/restaurant/_search {
"query": {
"filtered": {
"filter": {
"geo_bounding_box": {
"type": "indexed",
"location": {
"top_left": {
"lat": 40,8,
"lon": -74.0
},
"bottom_right": {
"lat": 40.4,
"lon": -73.0
}
}
}
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 40.715,
"lon": -73.998
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
寻找答案:
成员模板专精的名称出现在后缀表达式中的
template
或.
之后或之后 qualified-id 中的 nested-name-specifier , postfix-expression 的对象表达式取决于类型 或者 qualified-id 中的嵌套名称说明符是指依赖类型,但名称不是 在当前实例化(14.6.2.1)中,成员模板名称必须以关键字->
作为前缀。
但是虽然对名称有限制:
以关键字
template
为前缀的名称应为 template-id ,或者名称应引用类模板。
对它的“依赖性”没有任何限制:
[注意:与
template
前缀的情况一样,如果是typename
前缀,则允许template
前缀 不是绝对必要的;即嵌套名称说明符或->
或.
左侧的表达式 依赖于模板参数,或者使用不会出现在模板的范围内。 -end note]
所以以下内容总是可以正常编译:
struct X
{
template <typename >
void foo() { }
};
int main()
{
X{}.template foo<int >(); // template keyword not strictly necessary
}
真实的答案是:不要使用宏来做这样的事情。只需写出函数调用。以后每个人都会感谢你。通过在呼叫站点获得额外奖励,您可以了解是否需要template
关键字,因此您可以在必要时准确使用它。
答案 1 :(得分:1)
(首先,从不在宏的末尾添加;
。它会在某些if
次调用中中断。)
我认为您可以随时将template
放在foo
前面。有时它是必需的。有时它是可选的。但我不认为永远不允许template
立即出现在模板前面。
#define CALL_FOO(x) x.template foo<int>()
答案 2 :(得分:0)
对于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。