我有 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 的行为是否正确(看到对标准的引用会很酷)?
我需要进行哪些更改才能修复它?