【问题标题】:What is the proper way to use static_assert in a non-instantiation template? [duplicate]在非实例化模板中使用 static_assert 的正确方法是什么? [复制]
【发布时间】:2020-09-07 12:49:57
【问题描述】:

例如我有一些模板类:

template <typename T, typename = void>
struct A {
  void Print() {
    static_assert(false, "fall into unsupported Print function");
  }
};
// an instantiation if T is a unsigned type
template <typename T>
struct A<T, typename std::enable_if_t<std::is_unsigned<T>::value>> {
  void Print() {
    std::cout << "A<int>" << std::endl;
  }
};

但由于标准:

如果无法为模板定义生成有效的特化, 并且该模板未实例化,模板定义为 格式不正确,无需诊断。

无论模板类是否被实例化,clang 都会立即停止编译并显示失败,这不是我的本意。

我尝试了其他方法,例如添加 constexpr bool 函数以返回 false,但都失败了。

那么有什么技巧可以让static_assert 仅在模板类被实例化时触发?

【问题讨论】:

  • 欺骗是针对if constexpr,但同样的答案适用于模板专业化。

标签: c++ c++11 templates


【解决方案1】:

如果static_assert 中的表达式依赖于模板参数,则断言将延迟到实例化。例如,您可以定义以下类模板 deferred_false

#include <type_traits> // std::false_type

template<typename>
struct deferred_false: std::false_type {};

然后,在static_assert中使用它:

template <typename T, typename = void>
struct A {
  void Print() {
    static_assert(deferred_false<T>::value, "fall into unsupported Print function");
  }
};

【讨论】:

  • 虽然这在实践中有效,但它仍然不违反标准吗?
  • @Dani 为什么?我想说这只是利用模板的Two-Phase Lookup在第一阶段查找非依赖名称,而在第二阶段查找依赖模板参数的名称 (in the comment)。
  • @Dani 不,没关系,原因是可能deerred_false 的特化,其计算结果为true_type
猜你喜欢
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 2016-03-06
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多