9

为什么会这样编译:

class Testable {
public:
    template <bool flag>
    typename std::enable_if<flag>::type
    void foo() { cout << "Yay" << endl; }

    template <bool flag>
    typename std::enable_if<!flag>::type
    void foo() { cout << "Nay" << endl; }
};

但如果我使用默认类型定义两个 foo,则不是这样:

    template <bool flag, typename = typename std::enable_if<flag>::type>
    void foo() { cout << "Yay" << endl; } // (A)

    template <bool flag, typename = typename std::enable_if<!flag>::type>
    void foo() { cout << "Nay" << endl; } // (B)

我收到此错误(第一行指向 的定义(B),第二行指向(A)):

error: 'template<bool flag, class> void Testable::foo()' cannot be overloaded
error: with 'template<bool flag, class>> void Testable::foo()'
4

2 回答 2

9

编译器抱怨因为两个函数模板具有相同的签名。C++11 标准的第 1.3.18 段指定了函数模板的签名由以下内容定义:

<function template>名称、参数类型列表 (8.3.5)、封闭命名空间(如果有)、返回类型和模板参数列表

如您所见,默认模板参数不是签名的一部分。

您可以通过更改以下定义来解决此问题Testable

class Testable {
public:
    template <bool flag, typename std::enable_if<flag>::type* = nullptr>
    void foo() { cout << "Yay" << endl; } // (A)

    template <bool flag, typename std::enable_if<!flag>::type* = nullptr>
    void foo() { cout << "Nay" << endl; } // (B)
};
于 2013-04-26T17:56:04.897 回答
0

如前所述,两个函数不能具有相同的签名。

但是,我有不同的解决方法。

template<std::size_t>
struct secret_enum { enum class type {}; };
template<bool b, std::size_t n=0>
using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type;

class Testable {
public:
  template <bool flag, EnableIf<flag, 0>...>
  void foo() { cout << "Yay" << endl; } // (A)

  template <bool flag, EnableIf<!flag, 1>...>
  void foo() { cout << "Nay" << endl; } // (B)
};

0你用,等枚举你的重载1,这会生成一个可能的类型,然后你...说“0个或多个这些”,并且生成的类型基本上不可能生成enum实例。

可悲的是,这在 clang 3.2 中不起作用。它在 gcc 4.8 中执行。

于 2013-04-27T00:15:24.983 回答