【发布时间】:2022-01-22 00:55:44
【问题描述】:
我在 constexpr 上下文中的 Visual Studio 2022 (/std:c++latest) 中的默认移动构造函数存在问题。我在 Visual Studio 2019 中看不到此问题。我有两个问题:
- 是我的代码或 Visual Studio 2022 不正确吗?如果我的代码不正确,那为什么?
- 在 gcc 或 clang 中是否存在类似问题? (我目前确实可以使用这些编译器。)
问题陈述
在下面的代码中,我有两个真/假开关:
DEFAULT_MOVE 和 CONSTEXPR,因此给了我四个可能的程序。
-
DEFAULT_MOVE控制默认移动构造函数还是 使用自制的移动构造函数。 -
CONSTEXPR控制是否创建Container的实例 编译时或运行时。
当DEFAULT_MOVE 和CONSTEXPR 都为真时,代码不编译,产生消息:
error C3615: constexpr function 'Containerstd::u8string_view,3 ::Container' 不能产生常量表达式
但是,在三个开关组合中的任何其他组合下,代码编译成功。
我希望代码在所有四种情况下都能编译。
#include <array>
#include <cassert>
#include <string_view>
//switches
#define DEFAULT_MOVE true
#define CONSTEXPR true
template<typename T, size_t N>
struct Container{
std::array<T, N> x;
template<typename... Args>
constexpr explicit Container(Args&&...args) : x{std::forward<Args>(args)...} {}
#if DEFAULT_MOVE
//default move ctor
constexpr Container(Container&&) noexcept = default;
#else
//home-brew move ctor
constexpr Container(Container&& other) noexcept : x{} {
for (size_t n{0} ; T& e : other.x)
x[n++] = std::move(e);
}
#endif
constexpr Container(const Container&) = delete;
constexpr Container& operator=(Container&&) = delete;
constexpr Container& operator=(const Container&) = delete;
constexpr ~Container() = default;
};
using X = Container<std::u8string_view, 3>;
using Y = Container<X, 2>;
int main() {
#if CONSTEXPR
// constexpr creation of a Y object
constexpr Y a{X{u8"a",u8"b"}, X{u8"a"}};
static_assert(a.x[0].x[1] == u8"b");
#else
// runtime creation of a Y object
const Y a{X{u8"a",u8"b"}, X{u8"a"}};
assert(a.x[0].x[1] == u8"b");
#endif
}
【问题讨论】:
-
此问题已在 Visual Studio 最新版本中得到解决
标签: c++ c++20 constexpr visual-studio-2022 move-constructor