我有一个不能直接使用的类模板,只允许专业化。我想使用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
。因为MSVC doesn't将sizeof(arg)
视为模板相关的表达式(unlike GCC),但是decltype(sizeof(arg))
is fine。
有人可以用标准来解释这种行为吗?便携吗?
答案 0 :(得分:4)
此:
#define DEPENDENT_FALSE(arg) AlwaysFalse<decltype(sizeof(arg))>::value
不能真正依赖 。 decltype(sizeof(arg))
始终为size_t
,它实际上不以任何方式依赖于arg
(更广泛地说,这是一个list of expressions,从不依赖于类型)。由于不依赖,编译器完全能够看到DEPENDENT_FALSE(T)
是false
并只需触发该static_assert
。
您想要的只是:
#define DEPENDENT_FALSE(arg) AlwaysFalse<decltype(arg)>::value
也就是说,放下sizeof
。现在,这是依赖的。
这将不会直接对int
起作用,因为它不再依赖于(decltype(i)
只是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!");
};
答案 1 :(得分:-1)
也许是以下想法:
template<typename T>
struct AlwaysError
{
AlwaysError<T>()
{
std::cout << T::value << std::endl;
static_assert( T::value, "You must use specialization!");
}
};
template <typename T>
struct Foo: public AlwaysError<Foo<T>>
{
static constexpr bool value = false;
};
template <>
struct Foo<int>{};
int main()
{
//Foo<double> d; // error message as expected
Foo<int> i; // specialized, compiles!
}
assert消息包含文本和应专门化的类型。希望能有所帮助!
答案 2 :(得分:-1)
在C ++ 17上有效的解决方案。不幸的是我只有C ++ 11
template<auto>
constexpr bool dependentFalseHelper(){
return false;
}
template<class>
constexpr bool dependentFalseHelper(){
return false;
}
#define DEPENDENT_FALSE(arg) (dependentFalseHelper<arg>())