为什么此代码适用于 c++17,但不适用于 c++20 (MSVC)?

时间:2021-01-04 17:20:55

标签: c++ c++17 metaprogramming constexpr c++20

我有 constexpr_sequence 类,它在每次 next() 调用时返回新值,在 value() 调用中返回当前值,具体取决于作为模板参数给出的函数和起始值。例如:

template<typename T, T INC>
constexpr T increase(T val)
{
    return val + INC;
}

using counter = qx::constexpr_sequence<struct Tag, int, 0, increase<int, 1>>;
static_assert(counter::value() == 0);
static_assert(counter::next()  == 1);
static_assert(counter::value() == 1);
static_assert(counter::value() == 1);
static_assert(counter::next()  == 2);
static_assert(counter::value() == 2);
static_assert(counter::next()  == 3);
static_assert(counter::value() == 3);

此代码适用于 MSVC、Clang、Apple Clang 和 GCC 以及 C++17,但是当我启用 C++20 时对 MSVC 的测试失败(counter::value() 总是返回 0,尽管 {{ 1}} 一定要修改相应的标志。

类代码:

counter::next()

类将我的 template <class Tag, typename T, T Start, T Func(T)> class constexpr_sequence { private: template <T nIndex> struct Element { static constexpr T value(void) noexcept { T _value = Start; for (std::size_t i = 0; i < nIndex; i++) _value = Func(_value); return _value; } }; template<std::size_t nCurrent, bool bWasSetted /* = false */> struct CheckerSetter { static constexpr std::size_t index(void) noexcept { return nCurrent; } }; template<T nCurrent> struct CheckerWrapper { template<bool bWasSetted = constexpr_flag<Element<nCurrent>>{}.test(), std::size_t nNext = CheckerSetter<nCurrent, bWasSetted>{}.index()> static constexpr std::size_t index(void) noexcept { return nNext; } }; template<std::size_t nCurrent> struct CheckerSetter<nCurrent, /* bool bWasSetted = */ true> { template<std::size_t nNext = CheckerWrapper<nCurrent + 1>{}.index()> static constexpr std::size_t index(void) noexcept { return nNext; } }; public: template <std::size_t nIndex = CheckerWrapper<0>{}.index(), T _value = Element<nIndex>{}.value()> static constexpr T value(void) noexcept { return _value; } template <std::size_t nIndex = CheckerWrapper<0>{}.index(), T _value = Element<nIndex>{}.value(), bool bStub = constexpr_flag<Element<nIndex>>{}.test_and_set()> static constexpr T next(void) noexcept { return Func(_value); } }; 类作为依赖项,该类在开头返回“Start”(constexpr_flag),“Start”与 test() 和 {{1} 之后的“End” }.此代码的测试成功通过,但如果您认为问题出在这里,您可以检查一下。

回购:
constexpr_flag
constexpr_sequence
test_constexpr_flag
test_constexpr_sequence

重现问题:

test_and_set

构建将失败并显示 test()(并依赖于它们 git clone https://github.com/n0lavar/qxLib.git open qxLib\cmake\platform_options.cmake, change cxx_std_17 to cxx_std_20 git clone https://github.com/google/googletest.git cd googletest mkdir build cd build cmake .. cmake --build . cd .. cd .. cd qxLib mkdir build cd build cmake -DGENERATE_TESTS=1 .. cmake --build . test_constexpr_sequence

问题:
为什么这段代码不起作用?
MSVC 的行为是否正确(看到对标准的引用会很酷)?
我需要进行哪些更改才能修复它?

0 个答案:

没有答案