(反向)构造函数的转发保守性具有完美的转发

问题描述 投票:0回答:1

假设我有一个带有

consteval
构造函数的类,可确保编译时的值有效。 (还有一个
std::expected-returning
工厂方法可以在运行时验证其参数,但这与这个问题无关。)

class ConstevalConstructible {
 public:
  consteval ConstevalConstructible(int value) : value_(value) {
    // Validate value and fail compile if invalid.
  }
  // Copyable, movable, et cetera
 private:
  int value_;
}

现在假设我有一个可以保存任何值的通用包装结构:

template <typename T>
struct Wrapper {
  template <typename... Args>
  constexpr Wrapper(Args&&... args) : inner(std::forward<Args>(args)...) {}

  T inner;
};

由于

constexpr
允许在常量上下文中调用构造函数,因此包装器对于运行时构造和 constexpr 构造都可以正常工作:

// Fine
Wrapper<RuntimeConstructible> foo{runtime_value};
// Also fine: Wrapper's constexpr constructor is evaluated at compile
// time and thus the ConstexprConstructible's constructor is too.
constexpr Wrapper<ConstexprConstructible> bar{42};

ConstevalConstructible
Wrapper
一起使用时会出现问题:

// Fails to compile: the constexpr Wrapper constructor is not an
// immediate function, so it cannot invoke ConstevalConstructible's
// constructor using arguments that are not (within its body)
// constexpr.
Wrapper<ConstevalConstructible> foo{5};
// Doesn't fix the problem from the compiler's point of view.
constinit Wrapper<ConstevalConstructible> foo{5};
// This does work as long as ConstevalConstructible is movable or
// copyable, but gets annoying.
Wrapper<ConstevalConstructible> bar{ConstevalConstructible{5}};

问题是,虽然

constexpr
求值从外到内传播(变量声明上的
constexpr
导致
Wrapper
的构造函数在编译时求值,进而导致
ConstexprConstructible
的构造函数编译时评估),构造函数
consteval
-ness将需要从内到外传播(
ConstevalConstructible
的构造函数为
consteval
必须导致
Wrapper
的构造函数也为
consteval
,所以立即评估
Wrapper
的整个构造)。

这感觉类似于

noexcept
的工作方式,其中可以根据所包含的类型来指定方法是否抛出。但是,我不知道有类似的方法可以使构造函数或函数有条件地
consteval
。我考虑添加
consteval
重载,但我不确定如何限制它:

template <typename T>
struct Wrapper {
  template <typename... Args>
  constexpr Wrapper(Args&&... args) : inner(std::forward<Args>(args)...) {}
  template <typename... Args>
  consteval Wrapper(Args&&... args)
    requires requires { /** What would I put here? **/ }
    : inner(std::forward<Args>(args)...) {}

  T inner;
};

这在 C++20 中可以解决吗?如果没有,有计划在未来版本中出现吗?

c++ templates c++20 consteval
1个回答
0
投票

这个确切的问题已作为针对 C++20 的缺陷报告被解决了,因此最终应该可以在任何出售

consteval
的地方使用。

© www.soinside.com 2019 - 2024. All rights reserved.