如何打印对象的类型作为static_assert语句的一部分?



我写了一些类型转换操作符,它们只在类型的子集上下文中有意义。

下面是一个例子
explicit virtual operator DataId<float>() const
{
static_assert(std::is_same_v<T, DataId<float>>, "std::is_same_v<T, DataId<float>>");
return data; // T data
}

该类包含一个类型为T=DataId<U>的对象,其中U=float, int, double, std::string.

static_assert似乎要求传递给它创建错误消息的参数是const char*

是否有办法在消息中打印T的类型?

我试过了,但是失败了:

constexpr auto message(
(std::string("std::is_same_v<T=") + typeid(T).name() + ", DataId<float>>").c_str()
);
static_assert<..., message>;

根据https://en.cppreference.com/w/cpp/language/static_assert:

由于消息必须是字符串字面值,因此它不能包含动态信息,甚至不能包含本身不是字符串字面值的常量表达式。特别是它不能包含模板的名称类型参数。

因此,如果明确地说它不能包含模板名,我认为这是不可能的。

消息需要是字符串文字,所以您不能这样做。


更新的gcc/clang也已经输出std::is_same的类型。(gcc 11/clang 8)


对于不这样做的编译器,使得很难获得真正的类型。

一种可能的解决方法是将其封装在模板中,并使其成为硬错误,然后编译器可能会告诉您实例化的类型。

template<typename T, typename U>
consteval void assert_same(){
static_assert(
std::is_same_v<T, U>
);
}
// usage:
template<typename U>
struct X{
using T = std::vector<U>;
void foo(){
assert_same<T,float>();
}
};

将导致报告

'consteval void assert_same() [with T = XXX; U = XXX]'的实例化:

错误:static assertion failed

https://godbolt.org/z/Y7TEhM51f