以下代码无法在
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;
06001
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编译它没有错误.
如果我移动枚举类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.