首页 > 解决方案 > 模板依赖 false

问题描述

我有一个不能直接使用的类模板,只允许专门化。我想用它static_assert来显示有意义的错误信息。我不能只键入static_assert(false, "error");,因为false它不依赖于值,即使从未使用过模板,编译器也可能会显示错误消息。

我的解决方案:

template<class>
struct AlwaysFalse : std::false_type{};

#define DEPENDENT_FALSE(arg) AlwaysFalse<decltype(sizeof(arg))>::value

template<class T>
struct Foo{
    static_assert(DEPENDENT_FALSE(T), "You must use specialization!");
};

template<int i>
struct Bar{
    static_assert(DEPENDENT_FALSE(i), "You must use specialization!");
};

但我不确定实现DEPENDENT_FALSE。因为 MSVCsizeof(arg)其视为依赖于模板的表达式(与 GCC 不同),但decltype(sizeof(arg)) 很好

有人可以用标准来解释这种行为吗?它是便携式的吗?

标签: c++c++11templateslanguage-lawyer

解决方案


这个:

#define DEPENDENT_FALSE(arg) AlwaysFalse<decltype(sizeof(arg))>::value

没有真正依赖decltype(sizeof(arg))is always size_t,它实际上并不依赖arg于任何方式(更广泛地说,这里是一个从不依赖于类型的表达式列表)。由于它不依赖,编译器完全能够看到它DEPENDENT_FALSE(T)false触发它static_assert

你想要的只是:

#define DEPENDENT_FALSE(arg) AlwaysFalse<decltype(arg)>::value

也就是说,删除sizeof. 这现在依赖的。


这不适用于int直接,因为它不再是依赖的(decltype(i)is just int,我们现在需要一些依赖于价值的东西)。为此,您可以将其包装在一个整数常量中:

template<class T>
struct Foo{
    static_assert(AlwaysFalse<T>::value, "You must use specialization!");
};

template<int i>
struct Bar{
    static_assert(AlwaysFalse<std::integral_constant<int, i>>::value, "You must use specialization!");
};

推荐阅读