c++ - C++ (14/17) 使用枚举作为非类型模板参数时出现奇怪的无底模板递归错误
问题描述
以下代码:
#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);
}
无法使用 g++-5.4 或 g++-7.4(尝试 -std=c++14,-std=c++17)进行编译,这似乎是一个无底的模板递归错误:
<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
但是,如果我用EnumT
其中一个int
或范围枚举替换,一切都编译得很好。还要注意explicit
在第二个构造函数中注释掉的关键字。如果我取消注释,那么这个版本EnumT
也可以很好地编译。
任何人都可以解释到底发生了什么?提前致谢。
解决方案
推荐阅读
- django - 如何修复 Reactjs、Django、Django Rest Frame 工作项目中的“net::ERR_CONNECTION_REFUSED 和错误:网络错误”错误
- c# - 我有一个很长的代码,我不太明白,请帮助将代码分解为更简单的语句
- php - 如何使用 php 语言将 HTML“类”属性转换为 css 选择器?
- pandoc-citeproc - pandoc-citeproc 作为 API:processCites' 不添加引用
- python-3.5 - ImportError:没有名为“yolo_utils”的模块
- python - tkinter ttk OptionMenu 在更新选项列表时丢失复选标记突出显示
- python-3.x - ffmpeg-python 包装器 ffmpeg.run() 获取 FILENOTFOUNDERROR
- android - LinearLayout 添加多个项目
- python-3.x - aiohttp 和 asyncio 如何以并发方式从 http 请求和 websocket 获得响应?
- c# - 无法从 .NET Core 2 控制台应用程序中的 config.json 读取数据