如何将未明确的字符串文字错误消息传递给 static_assert?

How to pass a not explicitly string literal error message to a static_assert?

我在代码的不同地方有一些静态断言。

static_assert(bool_constexpr_1, error_message);
...
static_assert(bool_constexpr_2, error_message);

并希望所有人共享相同的 error_message

第一个解决方案是复制粘贴消息。

第二个是#define error_message.

还有更好的吗?

P.S。我希望 static constexpr auto 能工作,但它失败了。

您要么必须复制粘贴文字,要么使用预处理器。 Per [dcl.dcl]/1 static_assert 的语法定义为

static_assert-declaration:
      static_­assert ( constant-expression ) ;
      static_­assert ( constant-expression , string-literal ) ;

因此,您要么提供字符串文字,要么不提供。没有其他方法可以使用它。

你的问题听起来很像变体:

您已将其定义为通用的,但是,由于您想重复使用相同的 'error' 消息,我认为您的检查也将是相似的。让我们用一个你想强制继承的例子:

 struct Interface {};
 struct Impl : Interface {};
 struct Other {};
 static_assert(std::is_base_of_v<Interface, Impl>, "Implementations should inherit from the interface. See document at ... for more details."); // Success
 static_assert(std::is_base_of_v<Interface, Other>, "Implementations should inherit from the interface. See document at ... for more details."); // Failure

在这里,实现您自己的类型特征可能很有意义。例如:

 template<typename T> using FrameworkInjectionRequirement = std::is_base_of<Interface, T>
 template<typename T> constexpr bool FrameworkInjectionRequirement_v = FrameworkInjectionRequirement<T>::value;

  static_assert(FrameworkInjectionRequirement_v<Impl>);

通过这样做,您已经为您尝试检查的内容提供了一个好名字,这足以使用 static_assert 的简洁版本,而不需要解释。

或者,您可以将断言包装到一个结构中:

template<typename T>
struct FrameworkInjectionRequirement {
    static_assert(std::is_base_of_v<Interface, T>, "Implementations should inherit from the interface. See document at ... for more details.");
};
constexpr static FrameworkInjectionRequirement<Impl> check{}; // Success
constexpr static FrameworkInjectionRequirement<Other> check{}; // Failure

通过在编译时实例化此零大小结构(感谢变量上的 constexpr),将检查断言。 您不仅可以在其中重复使用该消息,而且您再次为您的支票取了一个好名字。作为奖励,您可以将创建布尔表达式的不同元素拆分为不同的元素,如果其中一个元素失败,这将对您有所帮助。