我正试图static_assert
使用某种元转换器算法,尽管typeid().name()
返回了完全相同的字符串,但它却难以与之相比。
在typedef中重复类型表达式可以修复is_same
,但是我不明白在typedef中重复初始化构造函数表达式如何改变类型,而不是采用自动变量的decltype用相同的表达式初始化。
关于我在做什么的更具体的解释:
我做了一个元转换器,可以将元值列表(包含枚举器)转换为所有枚举器的std :: tuple。然后我检查生成的元组是否是我期望的元组。
下面的所有代码,请在注释处检查// //无效//
最后的测试在最后。
#include <type_traits>
#include <tuple>
template<typename T> struct ValueListAsTuple; // master template
// destructurer of list:
template<template <auto...> class L, auto... Vs>
struct ValueListAsTuple<L<Vs...>>
{
static constexpr auto value = std::make_tuple(Vs...);
//using type = decltype(std::make_tuple(Vs...)); // works
using type = decltype(value); // doesn't work
};
// template typedef
template<typename T> using ValueListAsTuple_t = typename ValueListAsTuple<T>::type;
struct Kind
{
enum EnumType { E1, E2 };
template <auto... Values> struct MetaVals{}; // meta value list
using MetaValueList = MetaVals<
E1,
E2
>;
};
int main(int argc, const char* argv[])
{
auto tuple = ValueListAsTuple_t< Kind::MetaValueList > {};
//std::cout << typeid(tuple).name() << '\n';
// this prints: "class std::tuple<enum Kind::EnumType, enum Kind::EnumType>"
// manual re-creation of the type, for testing:
std::tuple< Kind::EnumType, Kind::EnumType > t2;
//std::cout << typeid(t2).name() << '\n';
// this prints the exact same thing.
static_assert( std::is_same_v< std::tuple_element<0, decltype(tuple)>::type, Kind::EnumType > );
static_assert( std::is_same_v< std::tuple_element<1, decltype(tuple)>::type, Kind::EnumType > );
// WHAT ???
static_assert( std::is_same_v<
ValueListAsTuple_t< Kind::MetaValueList >,
std::tuple< Kind::EnumType, Kind::EnumType >
> );
// is_convertible_v works but I don't care ! wth ?
}
如您所见,通过is_same
声明type
时,value
无法推断出相同的类型,但是如果我重复std::make_tuple(..
,它就可以工作。我看不出这两种表格之间有什么区别。
我甚至逐个元素地检查了元组的每个索引的类型是否相同。
在“ godbolt”中检查其作用:
https://godbolt.org/z/QUCXMB
gcc / clang / msvc中的行为相同
答案 0 :(得分:5)
这确实是一个小错误,但不幸的是很难发现。您面临的问题是因为constexpr
意味着const
。因此,在您的示例中,type
是const tuple<...>
,它与您检查的非cv限定类型不同。对别名的简短修正应使您的测试通过:
using type = std::remove_const_t<decltype(value)>;