我有SFINAE的问题。我错过了一些重要的事情并且阅读其他问题没有帮助:(
以下是代码:
#include <string>
#include <type_traits>
#include <iostream>
// version with template class
template<typename T, typename = std::enable_if_t<
std::is_integral<std::remove_reference_t<T>>::value
|| std::is_floating_point<std::remove_reference_t<T>>::value
>
>
struct to_my_string
{
std::string operator()(T numerical)
{
return std::to_string(numerical);
}
};
template<typename T, typename = std::enable_if_t< std::is_same<T, std::string>::value > >
struct to_my_string
{
std::string operator()(T str)
{
return "'" + str + "'";
}
};
// version with template method
template<typename T, typename = std::enable_if_t<
std::is_integral<std::remove_reference_t<T>>::value
|| std::is_floating_point<std::remove_reference_t<T>>::value
>
>
std::string to_string_method(T numerical)
{
return std::to_string(numerical);
}
template<typename T, typename = std::enable_if_t< std::is_same<T, std::string>::value > >
std::string to_string_method(T str)
{
return "'" + str + "'";
}
int main()
{
std::cout << "start" << std::endl;
return 0;
}
我已经粘贴了两种方法 - 一种类和一种方法。两者产生类似的错误: 以下是g ++的错误(clang给出了类似的错误):
g++ --std=c++14 sfinae_failure.cpp
sfinae_failure.cpp:21:12: error: redefinition of default argument for ‘class<template-parameter-1-2>’
struct to_my_string
^
sfinae_failure.cpp:7:26: note: original definition appeared here
template<typename T, typename = std::enable_if_t<
^
sfinae_failure.cpp:43:17: error: redefinition of ‘template<class T, class> std::__cxx11::string to_string_method(T)’
std::string to_string_method(T str)
^
sfinae_failure.cpp:37:17: note: ‘template<class T, class> std::__cxx11::string to_string_method(T)’ previously declared here
std::string to_string_method(T numerical)
^
我的主要问题是为什么它不起作用,即使我在enable_if_t中使用T类型。我错过了什么?
附加的问题是 - 我认为模板类/方法在使用时会被实例化。正如你在主方法中看到的那样 - 它们不是。
即使这个话题被多次触及,我也非常感谢你的帮助......
答案 0 :(得分:2)
您的课程模板的错误是因为您无法重新定义课程模板,它与SFINAE无关。
template<class A = int> struct foo {};
template<class A = double> struct foo {};
即使没有实例化,这段代码也无法编译。
您的函数的错误是因为默认模板参数不是函数模板参数签名的一部分。
template<class A, class B = int> void bar() {}
template<class A, class B = double> void bar() {}
即使没有实例化,这段代码也无法编译,因为它们的模板参数签名是相同的:
template<class A, class B> void bar() {}
因此重新定义。
答案 1 :(得分:1)
修正版本:
template<typename T, typename Enabler = void> struct to_my_string;
template <typename T>
struct to_my_string<T, std::enable_if_t<
std::is_integral<std::remove_reference_t<T>>::value
|| std::is_floating_point<std::remove_reference_t<T>>::value
>>
{
std::string operator()(T numerical) const
{
return std::to_string(numerical);
}
};
template<typename T>
struct to_my_string<T, std::enable_if_t<std::is_same<T, std::string>::value>>
{
std::string operator()(const T& str) const
{
return "'" + str + "'";
}
};
// version with template method
template<typename T, std::enable_if_t<
std::is_integral<std::remove_reference_t<T>>::value
|| std::is_floating_point<std::remove_reference_t<T>>::value
, void*> = nullptr
>
std::string to_string_method(T numerical)
{
return std::to_string(numerical);
}
template<typename T, std::enable_if_t< std::is_same<T, std::string>::value, void*> = nullptr>
std::string to_string_method(T str)
{
return "'" + str + "'";
}