以下代码无法在 gcc 4.8.1 到 6.3 中编译:
#include <cassert>
template<typename T, T X>
struct Mode {
using type = Mode;
using value_type = T;
static constexpr value_type value = X;
^^^ error: 'constexpr const value_type Mode<main()::TestEnum, (main::TestEnum)0>::value', declared using local type 'const value_type {aka const main()::TestEnum}', is used but never defined [-fpermissive]
constexpr operator value_type() const noexcept { return value; }
};
int main()
{
enum class TestEnum { test1, test2 };
constexpr Mode<TestEnum, TestEnum::test1> test1 = {};
constexpr Mode<TestEnum, TestEnum::test2> test2 = {};
assert(static_cast<TestEnum>(test1) == TestEnum::test1);
}
clang 3.9.1和MSVC 2015 SP3编译无误
如果我将 enum class TestEnum { test1, test2 };
移动到全局范围内,那么它可以正确编译。
代码是否合法?还是我做错了什么?
最佳答案
我认为问题是,您仍然必须定义 Mode::value
,正如编译器所说 (ODR)。如果我没记错的话,这会随着 C++17 发生变化,并且定义不再是强制性的,这解释了为什么它使用 std=c++1z
标志运行。
这也在“之前”std=c++1z
编译和运行:
#include <cassert>
template<typename T, T X>
struct Mode {
using type = Mode;
using value_type = T;
static constexpr value_type value = X;
constexpr operator value_type() const noexcept { return value; }
};
template<typename T, T X> constexpr T Mode<T,X>::value;
int main()
{
enum class TestEnum { test1, test2 };
constexpr Mode<TestEnum, TestEnum::test1> test1 = {};
//constexpr Mode<TestEnum, TestEnum::test2> test2 = {};
assert(static_cast<TestEnum>(test1) == TestEnum::test1);
}
您可以 see it live .
关于c++ - 我可以使用本地声明的枚举类作为模板非类型参数吗? (gcc 给出模糊的错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42328208/