c++ - 为什么此代码适用于 c++17,但不适用于 c++20 (MSVC)?
问题描述
我有一个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,尽管counter::next()
DO 修改了相应的标志。
课程代码:
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);
}
};
类将我的constexpr_flag
类作为依赖项,该类在开头(test()
)处返回“开始”,在 之后返回“开始”test_and_set
和“结束” test()
。此代码的测试成功通过,但如果您认为问题出在此处,您可以检查它。
回购:
constexpr_flag
constexpr_sequence
test_constexpr_flag
test_constexpr_sequence
要重现问题:
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
(并依赖于它们test_constexpr_random
和test_rtti
)
问题:
为什么这段代码不起作用?
MSVC 的行为是否正确(看到对标准的引用会很酷)?
我需要进行哪些更改才能修复它?
解决方案
推荐阅读
- python - 如何从 mpts udp(一组带有 id 的程序)到带有一个程序 id(spts)的视频流
- javascript - 如何在javascript中将多个对象转换为键值对的数组[]
- javascript - 一旦评估为真,“删除”测试条件
- react-native - 在抽屉堆栈之间传递参数 react-navigation
- java - 如何从Java子目录中的类创建对象
- scala - 如何将 Flink DataSet 元组转换为一列
- c# - 在启动时设置 cookie (MVC .Net Core)
- java - 如何在相同的比较方法中也对名字进行排序
- android - 用于音频设备的 Android 蓝牙配对
- elasticsearch - Logstash 是否维护注册表文件?