std :: is_same不能通过constexpr auto变量的decltype工作

问题描述 投票:2回答:1

我试图static_assert一些元变换器算法工作,并且它令人难以置信地没有相同,即使typeid().name()返回完全相同的字符串。

在typedef中重复类型表达式可以修复is_same,但我无法理解在typedef中重复初始化表达式如何更改类型,而不是使用相同表达式初始化的auto变量的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的行为相同

c++ metaprogramming typetraits is-same
1个回答
5
投票

实际上,这是一个微不足道的错误,但很遗憾很难发现。你面临的问题是因为constexpr暗示const。因此,在您的示例中,typeconst tuple<...>,它与您检查的非cv限定类型的类型不同。对别名的简短修复应该使您的测试通过:

using type = std::remove_const_t<decltype(value)>;
© www.soinside.com 2019 - 2024. All rights reserved.