如何在不知道类是否为模板的情况下调用模板化成员函数?

时间:2015-07-14 03:22:42

标签: c++ templates macros

假设我有以下宏:

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的宏?

3 个答案:

答案 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