【发布时间】:2018-11-18 01:39:26
【问题描述】:
给定以下代码 (https://wandbox.org/permlink/Eof3RQs49weJMWan)
#include <tuple>
#include <type_traits>
#include <utility>
template <typename T>
inline constexpr auto always_false = false;
template <typename T>
class HardError {
static_assert(always_false<T>);
};
int main() {
std::ignore = std::conjunction<std::false_type, HardError<int>>{};
}
我试图理解为什么上面使用的std::conjunction 不会出错。我知道这是为了允许短路,因此不会发生这种情况,这是设计使然。
但是,我不明白允许这种情况发生的语言规则。鉴于下面std::conjunction的实现
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
我们最终继承了 std::conditional 的这种特化
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };
这需要两种类类型进行实例化。那么conjunction<Bn...>是如何被语言省略的呢?
【问题讨论】:
-
现在,将
typedef HardError<int> zz;添加到您的示例代码中。这也将编译没有任何错误。现在,尝试实例化zz,只有然后会出现错误。仅仅因为引用了具有失败的静态断言的类不会触发静态断言,但是当您尝试创建该类的实例时。在解开std::conjunction期间没有实例化HardError。 -
另外,根据[temp.res]/8.1,我认为是格式不正确,不需要诊断
标签: c++ templates language-lawyer metaprogramming