c++ template instantiation works with int, long, etc. but not float, double, etc
我正在研究一个小C++项目,为此我创建了一个漂亮的、方便的EDCOX1×0封装,称为EDCOX1×1。
在类中,我定义了一个模板化的运算符:
1 2 3 4 | template<typename T, typename std::enable_if_t<std::is_arithmetic<T>::value, T> = 0> friend Logger& operator<<(Logger& logger, const T& logMessage) { return logger << std::to_string(logMessage); // there is also an operator overload which takes a std::string& as argument. } |
当模板显示为整型时,如
1 2 | someLoggerInstance << 123 << 456ULL <<" "; |
编译得很好。
但是如果我把声明改为
1 2 | someLoggerInstance << 12.3 <<" "; |
编译器冲我大喊,模板无法实例化。
来自编译器的错误消息:
1 | Candidate template ignored: substitution failure [with T = double]: a non-type template parameter cannot have type 'typename std::enable_if_t::value, double>' (aka 'double') |
问题出在哪里?
我试图用
如果我为
1 2 3 | friend Logger& operator<<(Logger& logger, const double& logMessage) { return logger << std::to_string(logMessage); } |
问题变得更严重,因为编译器试图在最后传递
"
1 | Candidate function not viable: no known conversion from 'const unsigned char [1]' to 'const double' for 2nd argument |
和
1 | Candidate function not viable: no known conversion from 'const unsigned char [1]' to 'const std::string' (aka 'const basic_string, allocator >') for 2nd argument |
任何帮助或建议都很好!谢谢您!
编辑
谢谢你的快速帮助。
现在更改模板如下:
1 2 | template<typename T, typename TEnable = std::enable_if_t<std::is_arithmetic<T>::value && !std::is_same<T, char>::value, T>> friend Logger& operator<<(Logger& logger, const T& logMessage); |
型
当
但非类型模板参数显式地不允许是浮点类型。对于您的问题,正确的最小示例是:
1 2 | template<double d> // this is ill-formed void foo() {} |
号
其基本原理是,模板是根据非类型参数的确切值专门化的。这是一个类型的问题,直接相等的比较是有问题的。
只需让
型
为了解决第一个问题,另一种方法是使用
1 2 3 4 5 6 | template <typename T> std::enable_if_t<std::is_arithmetic<T>::value, Logger&> friend operator<<(Logger& logger, const T& logMessage) { return logger << std::to_string(logMessage); } |
你的第二个问题是因为
型
更新模板以使用类型模板参数:
1 2 3 4 5 6 7 8 | template < typename T , typename TEnabled = typename std::enable_if_t<std::is_arithmetic<T>::value, T> > friend Logger & operator <<(Logger & logger, const T & logMessage) { return logger << std::to_string(logMessage); } |