使用 std::enable_if 有什么问题?

nak*_*iya 6 c++ templates c++11

我有一个函数set_data,我必须针对它所接受的不同类型以不同的方式实现。例如,这试图根据输入类型实现两个重载。如果是 basic、nonvoid和 non nullptr_t,则在第一次实现时处理。如果是astd::stringcharbuffer,则采用第二种方式处理。

struct field
{
    template<typename TDataType, typename=void>
    void set_data(TDataType data, size_t index = 0);
};

template<typename TDataType, typename = typename
        std::enable_if< std::is_fundamental<TDataType>::value &&
                        std::is_same<TDataType, nullptr_t>::value == false &&
                        std::is_same<TDataType, void>::value == false>::type>
void field::set_data(TDataType data, size_t index /* = 0 */)
{
}

template<typename TDataType, typename = typename
        std::enable_if< std::is_same<std::string const &, TDataType> ||
                        std::is_same<char const *, TDataType>>::type>
void field::set_data(TDataType data, size_t index /* = 0 */)
{
}
Run Code Online (Sandbox Code Playgroud)

然后我打电话:

field f;
int x = 10;
f.set_data(x);
Run Code Online (Sandbox Code Playgroud)

编译器向我抛出错误。

defs.h(111): error C2995: 'void messaging::field::set_data(TDataType,size_t)' : function template has already been defined
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?

关于视觉工作室 2013

Tri*_*dle 3

在这样的模板参数上使用 SFINAE 不起作用,我想我不是 100% 确定为什么(编辑: Agnew 的答案解释说这是因为模板无法区分)。如果您改为使用std::enable_if返回类型,并在类中移动定义,那么它可以工作(使用 gcc 和 clang 进行测试):

struct field
{
    template<typename TDataType>
    void set_data(TDataType data, size_t index = 0) {}

    template<typename TDataType>
    typename std::enable_if<std::is_fundamental<TDataType>::value &&
                            !std::is_same<TDataType, std::nullptr_t>::value &&
                            !std::is_same<TDataType, void>::value,
                            void>::type
    set_data(TDataType data, size_t index /* = 0 */)
    {
    }

    template<typename TDataType>
    typename std::enable_if<std::is_same<std::string const &, TDataType>::value ||
                            std::is_same<char const *, TDataType>::value,
                            void>::type
    set_data(TDataType data, size_t index /* = 0 */)
    {
    }

};
Run Code Online (Sandbox Code Playgroud)

(我还修复了其他几个错误,即不要求第二个重载valuestd::is_sameint 成员,并且不指定 的命名空间std::nullptr_t)。