我有一个函数 set_data
,我必须针对它接收的不同类型以不同的方式实现它。例如,它试图根据输入类型实现两个重载。如果是基本的,非void
和非nullptr_t
,则在第一次实现时处理它。如果它是 std::string
或 char
缓冲区,则以第二种方式处理它。
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)
{
}
};
此外,请注意,如果函数模板的参数是按值传递的,则永远无法将模板参数推导出为引用类型。所以is_same<std::string const &, TDataType>
只有当模板参数 std::string const &
时才能为真在调用站点上明确指定。您可能希望通过检查 std::string
来替换它.甚至可能值得投入一些 std::remove_reference
和 std::remove_cv
正确处理明确指定的模板参数。
关于c++ - 使用 std::enable_if 有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26753393/