1

假设以下相当简单的类:

struct A {
    bool toBool() const { return true; }
    template<typename T> T to() const { return T();}
};

现在,我想测试是否存在toBool

template<typename From, typename To>
class has_toBool_func
{
    typedef char (&Two)[2];
    template<typename F, bool (F::*)() const> struct helper {};
    template<typename F> static char test(helper<F, &F::toBool>*);
    template<typename F> static Two test(...);
public:
    static const bool value = (sizeof(test<From>(0)) == sizeof(char));
};

定义和使用:

::std::cout << "int: " << has_toBool_func<int, bool>::value
    << ", A: " << has_toBool_func<A, bool>::value << ::std::endl;

并且只产生预期的输出“int:0,A:1”。

为函数模板尝试同样的事情:

class has_to_func
{
    typedef char (&Two)[2];
    template<typename F, To (F::*)() const> struct helper {};
    template<typename F> static char test(helper<F, &F::to<To> >*);
    template<typename F> static Two test(...);
public:
    static const bool value = (sizeof(test<From>(0)) == sizeof(char));
};

::std::cout << "int: " << has_to_func<int, bool>::value
    << ", A: " << has_to_func<A, bool>::value << ::std::endl;

不会产生预期的输出“int:0,A:1”,而是编译错误。

为什么会这样?当然:我该如何解决它?

MSVC 2012

发出警告

warning C4346: 'F::to' : dependent name is not a type  
      prefix with 'typename' to indicate a type  
      see reference to class template instantiation 'xtd::has_to_func<From,To>' being compiled

这是没用的,因为依赖名称实际上不是类型和错误

error C2998: 'char test' : cannot be a template definition

这也不是很有帮助......

国际商会 13.0

首先给出错误

error : type name is not allowed  
        template<typename F> static char test(helper<F, &F::to<To>() >*);  

<To>已标记)

它描述了问题,但仍然让我完全不知道为什么会发生这种情况以及另一个错误

error : expected a ")"  
        template<typename F> static char test(helper<F, &F::to<To>() >*);  

(最后一个>被标记)

我很确定这完全是胡说八道,只是因为编译器感到困惑才显示出来。

4

1 回答 1

4

&F::to<To>作为模板参数传递给时,不应使用括号helper,并且应使用template消歧器告诉编译器:

  • to应该被解释为模板的名称;
  • 随后的尖括号应分隔模板参数,而不是被解释为小于大于

template<typename F> static char test(helper<F, &F::template to<To> >*);
//                                              ^^^^^^^^^^^^^^^^^^^

添加T为 的返回类型后A::to<>(),这似乎对我有用(在 GCC 4.7.2 上测试)。这是一个活生生的例子

于 2013-05-07T08:35:00.163 回答