c++ - 使用 std::enable_if 有什么问题?

标签 c++ templates c++11

我有一个函数 set_data,我必须针对它接收的不同类型以不同的方式实现它。例如,它试图根据输入类型实现两个重载。如果是基本的,非void和非nullptr_t,则在第一次实现时处理它。如果它是 std::stringchar 缓冲区,则以第二种方式处理它。

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 */)
{
}

然后我这样调用:

field f;
int x = 10;
f.set_data(x);

然后编译器向我抛出一个错误。

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

我该如何解决?

关于 Visual Studio 2013

最佳答案

您试图在类的外部 定义重载,这当然是不允许的。或者您可能正在尝试为成员函数模板提供两个部分特化,但函数模板不能部分特化。

您需要摆脱公共(public)声明并将两个重载移动到类中。但是,您必须使它们易于区分。您可以通过为其中之一提供一个额外的模板参数(并向第二个重载添加一些缺失的 ::value)来做到这一点:

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

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

Live example

此外,请注意,如果函数模板的参数是按值传递的,则永远无法将模板参数推导出为引用类型。所以is_same<std::string const &, TDataType>只有当模板参数 std::string const & 时才能为真在调用站点上明确指定。您可能希望通过检查 std::string 来替换它.甚至可能值得投入一些 std::remove_referencestd::remove_cv正确处理明确指定的模板参数。

关于c++ - 使用 std::enable_if 有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26753393/

相关文章:

c++ - decltype 不推导 const 对象的 const 成员

c++ - 将 std::format 与自定义类型一起使用

c++ - 后增量运算符行为

C++ 模板友元运算符与另一个类似的运算符

c++ - 为什么这样调用构造函数时模板参数推导失败?

c++11 - g++4.9.2 和右值引用映射

c++ - Qt C++ 中对库方法的 undefined reference

c++ - 使用指向类的指针分配错误

c++ - 通过自由函数或成员函数进行扩展的机制

c++ - 如何在非可变参数模板类中形成可变参数模板函数?