C++ 歧义重载

Add*_*ddy 2 c++ templates overloading

考虑以下:

#include <string>

template <typename T, 
    typename std::enable_if<(
        std::is_integral<T>::value 
        && !std::is_same<T, bool>::value
    )>::type = 0>
void add(T val)
{
}

void add(bool val)
{
}

void add(const char* val)
{
}

int main()
{
    add(true);
    add("hi");
    add(0);
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨这add(0);是模棱两可的:

[x86-64 clang 6.0.0 #1] 错误:对“add”的调用不明确

我认为这是因为0可以隐式转换为boolor const char*。但是,我希望编译器选择模板化方法,而不必强制转换0(即add((int)0);)或指定模板化类型(即add<int>(0);)。

我还尝试将模板签名更改为:

template <typename T, 
    typename std::enable_if<(
        std::is_integral<T>::value 
        && !std::is_same<T, bool>::value
        && !std::is_same<T, unsigned char>::value
    )>::type = 0>
void add(T val)
...
Run Code Online (Sandbox Code Playgroud)

但这也无济于事。我怎样才能让它按照我想要的方式工作?

谢谢!

Oli*_*ohn 5

enable_if具有第二个模板参数,默认为void,并定义type条件为 时的true。 typename void = 0不编译,这就是函数不能成为重载决议的一部分的原因。但是typename int = 0确实可以编译,因此传递int使函数成为重载解析的一部分:

template <typename T,
    typename std::enable_if<(
        std::is_integral<T>::value 
        && !std::is_same<T, bool>::value
        && !std::is_same<T, unsigned char>::value
    ), int>::type = 0>
void add(T val)
{
}
Run Code Online (Sandbox Code Playgroud)

你也可以这样写,不传递第二个参数,我认为更简单:

template <typename T,
    typename = typename std::enable_if<(
        std::is_integral<T>::value 
        && !std::is_same<T, bool>::value
    )>::type>
void add(T val)
{
}

void add(bool val)
{
}

void add(const char* val)
{
}

int main()
{
    add(true);
    add("hi");
    add(0);       // A
    add<int>(0);  // B
    // A and B call the same function
}
Run Code Online (Sandbox Code Playgroud)

  • 另一种选择可能是`typename std::enable_if&lt;(std::is_integral&lt;T&gt;::value &amp;&amp; !std::is_same&lt;T, bool&gt;::value)&gt;::type * = nullptr&gt;` (2认同)