简体   繁体   English

std :: is_same无法通过constexpr自动变量的decltype工作

[英]std::is_same doesn't work through decltype of constexpr auto variable

I was trying to static_assert that some meta transformer algorithm worked, and it incredibly did not compare to same, even though the typeid().name() returned the exact same string. 我正在尝试static_assert一些元转换器算法工作,并且即使typeid().name()返回了完全相同的字符串,它也难以与之相比。

A repetition of the type expression in the typedef could fix the is_same , but I can't understand how repeating the initializer expression in the typedef changes the type, over taking the decltype of an auto variable initialized with that same expression . 在typedef中重复类型表达式可以修复is_same ,但是我不理解在typedef中重复初始化 is_same 函数表达式会如何改变类型,而不是使用用同一表达式初始化的auto变量的decltype

A more concrete explanation of what I was doing: 我正在做什么的更具体的解释:
I did a meta transformer that can transform a meta value list (containing enumerators) to a std::tuple of all enumerators. 我做了一个元转换器,可以将元值列表(包含枚举器)转换为所有枚举器的std :: tuple。 Then I checked that the tuple generated was the one I expected. 然后,我检查生成的元组是否是我所期望的。

all code hereunder, check the line with the comments // works // doesn't work 下面的所有代码,请在注释行中// //起作用//不起作用
And the final test is at the end. 最后的测试在最后。

#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 ?
}

So as you can see, is_same could not deduce the same type when the type was declared through value but it worked if I repeat std::make_tuple(.. . I can't see where there is any difference between the 2 forms. 因此,大家可以看到, is_same当不能推断出相同类型的type通过声明value ,但它的工作,如果我重复std::make_tuple(..我看不出哪里有2种形式之间的任何差别。

I even checked element by element that the types are the same at each index of the tuple. 我什至逐个元素地检查了元组的每个索引的类型是否相同。

Check that in action in godbolt: 检查一下Godbolt中的动作:
https://godbolt.org/z/QUCXMB https://godbolt.org/z/QUCXMB

The behavior is the same across gcc/clang/msvc 在gcc / clang / msvc中,行为是相同的

It's a trivial error, really, but hard to spot unfortunately. 确实,这是一个小错误,但不幸的是很难发现。 The issue you face is because constexpr implies const . 您面临的问题是因为constexpr隐含const So in your example type is const tuple<...> , which is not the same type as the non cv-qualified type you check. 因此,在示例中, typeconst tuple<...> ,它与您检查的非cv限定类型不同。 A short fix to the alias should make your test pass: 对别名的简短修正应使您的测试通过:

using type = std::remove_const_t<decltype(value)>;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM