如何将未显式字符串文字错误消息传递给static_assert?

时间:2019-08-14 19:39:28

标签: c++ string-literals 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可以工作,但是失败了。

2 个答案:

答案 0 :(得分:4)

您要么复制粘贴文字,要么使用预处理器。根据{{​​3}},static_assert的语法定义为

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

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

答案 1 :(得分:3)

您的问题听起来很像变体:How to make static_assert block re-usable in template classes?

您已经将其定义为泛型,但是,由于您想重用相同的“错误”消息,因此我认为您的检查也将类似。让我们使用一个示例,在其中您要强制继承:

 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),将检查断言。 您不仅可以重复使用邮件,还可以给支票起好名字。另外,您可以将创建布尔表达式的不同元素拆分为不同的元素,如果其中之一失败,将为您提供帮助。