C++ C++;(14/17)将枚举用作非类型模板参数时出现奇怪的无底模板递归错误
以下代码:C++ C++;(14/17)将枚举用作非类型模板参数时出现奇怪的无底模板递归错误,c++,c++14,c++17,enumeration,template-specialization,C++,C++14,C++17,Enumeration,Template Specialization,以下代码: #include <iostream> #include <type_traits> enum EnumT{Invalid = 0, Float, N_Types};//enum triggers the problem; works fine with ints template<typename T, EnumT id_> struct X { template<EnumT id = id_, std::en
#include <iostream>
#include <type_traits>
enum EnumT{Invalid = 0, Float, N_Types};//enum triggers the problem; works fine with ints
template<typename T, EnumT id_>
struct X
{
template<EnumT id = id_,
std::enable_if_t<(id != Float)> * = nullptr>
constexpr explicit X(T v): val_(v)
{
std::cout<<"cnstr..."<<id<<"\n";
}
template<EnumT id = id_,
std::enable_if_t<(id == Float)> * = nullptr>
constexpr /*explicit*/ X(float v): val_(v)
{
std::cout<<"cnstr..."<<id<<"\n";
}
template<typename OUT,
EnumT id = id_,
std::enable_if_t<(id == Float)> * = nullptr>
explicit operator OUT() const
{
std::cout<<"conv. op....\n";
return static_cast<float>(val_);
}
private:
T val_;
};
using Y = X<float, Float>;
bool operator==(Y const &lhs, Y const &rhs){
return static_cast<float>(lhs) == static_cast<float>(rhs);
}
#包括
#包括
枚举枚举{Invalid=0,Float,N_类型}//枚举触发了问题;可以很好地处理ints
模板
结构X
{
模板
constexpr显式X(tv):val_v(v)
{
标准::cout
| ^~~~~~~
编译终止。
返回的编译器:1
但是,如果我用int
或作用域枚举替换EnumT
,则一切都可以正常编译。还要注意在第二个构造函数中注释掉的explicit
关键字。如果我取消注释它,则使用EnumT
的此版本也可以正常编译
任何人都可以解释到底发生了什么?提前谢谢。你确定它可以用作用域枚举编译好吗?真的很奇怪。使用
操作符!=
,使用操作符==
失败。学习者:是的。只需将枚举枚举枚举
替换为枚举类枚举
并将浮点
替换为枚举::F即可loat
(在cout
中,用static\u cast(id)
)替换id
)并试一试。它对我来说编译得很好。而且……所有东西都可以编译得很好w/clang8.0.0.:因此,有两个问题,其中至少有一个似乎是编译器错误:(1)=
在EnumT
之间触发重载解析,其中操作符==(consty&,consty&)
成为候选;(2)操作符==(consty&,consty&)
触发Y
构造函数的实例化;我最感兴趣的是为什么(2)会发生?这是预期的还是一个bug?
<source>: In substitution of 'template<EnumT id, std::enable_if_t<(id == Float), void>* <anonymous> > constexpr X<float, Float>::X(float) [with EnumT id = Float; std::enable_if_t<(id == Float), void>* <anonymous> = <missing>]':
<source>:17:48: recursively required by substitution of 'template<EnumT id, std::enable_if_t<(id == Float), void>* <anonymous> > constexpr X<float, Float>::X(float) [with EnumT id = Float; std::enable_if_t<(id == Float), void>* <anonymous> = <missing>]'
<source>:17:48: required by substitution of 'template<EnumT id, std::enable_if_t<(id == Float), void>* <anonymous> > constexpr X<float, Float>::X(float) [with EnumT id = Float; std::enable_if_t<(id == Float), void>* <anonymous> = <missing>]'
<source>:26:48: required by substitution of 'template<class OUT, EnumT id, std::enable_if_t<(id == Float), void>* <anonymous> > X<float, Float>::operator OUT<OUT, id, <enumerator> >() const [with OUT = float; EnumT id = Float; std::enable_if_t<(id == Float), void>* <anonymous> = <missing>]'
<source>:39:34: required from here
<source>:17:48: fatal error: template instantiation depth exceeds maximum of 900 (use '-ftemplate-depth=' to increase the maximum)
17 | std::enable_if_t<(id == Float)> * = nullptr>
| ^~~~~~~
compilation terminated.
Compiler returned: 1