为什么 decltype(*this)::value_type 编译不?[复制]

Why doesn't decltype(*this)::value_type compile? [duplicate]

提问人:digito_evo 提问时间:9/17/2022 更新时间:9/17/2022 访问量:254

问:

为什么不编译?它显示一条错误消息:decltype(*this)

error: 'value_type' is not a member of 'const Foo<char>&'

那么,在下面的程序中无法编译的原因究竟是什么:decltype( *this )::value_type

#include <iostream>
#include <vector>
#include <type_traits>


template <typename charT>
struct Foo
{
    using value_type = charT;

    std::vector<value_type> vec;

    void print( ) const;
};

template <typename charT>
void Foo<charT>::print( ) const
{
    using Foo_t = std::remove_reference_t<decltype( *this )>;

                                   // `decltype( *this )::value_type` does not compile
    if constexpr ( std::is_same_v< typename Foo_t::value_type,
                                   decltype( std::cout )::char_type > )
    {
        // logic
    }
    else if constexpr ( std::is_same_v< typename Foo_t::value_type,
                                        decltype( std::wcout )::char_type > )
    {
        // logic
    }
    else
    {
        static_assert( std::is_same_v< typename Foo_t::value_type,
                                       decltype( std::cout )::char_type > ||
                       std::is_same_v< typename Foo_t::value_type,
                                       decltype( std::wcout )::char_type >,
                       "character type not supported" );
    }
}

int main( )
{
#define IS_CHAR 1

#if IS_CHAR == 1
    using FooChar = Foo<char>;
    FooChar foo;
    foo.vec.resize( 10, '$' );
#else
    using FooWideChar = Foo<wchar_t>;
    FooWideChar foo;
    foo.vec.resize( 10, L'#' );
#endif

    foo.print( );
}

指针有什么特别之处?为什么删除引用会使其编译?在上面的片段中一切正常。但是,如果我用更具可读性的替换,它将无法编译。因此,我尝试了一下运气,并设法提出了上述不太简单(且不太直观)的解决方案:thisstd::remove_reference_ttypename Foo_t::value_typedecltype( *this )::value_typestd::remove_reference_t

using Foo_t = std::remove_reference_t<decltype( *this )>;

// and then inside the std::is_same_v
std::is_same_v< typename Foo_t::value_type, /* etc */ >
// ...

我知道有更简洁的替代方案,例如 甚至,但我发现这种方法更不言自明。还有其他解决方案吗?std::is_same_v< Foo<charT>::value_type,std::is_same_v< charT,decltype

C++ 类型特征 decltype 是相同的

评论

0赞 NathanOliver 9/17/2022
T和是不同的类型,就像 和 一样。指针和引用没有指向/引用的事物的成员。T&TT*
0赞 François Andrieux 9/17/2022
@NathanOliver 问题是,当 的结果不是引用时,为什么是引用类型。我找到了一个副本。decltype(*this)*this
0赞 Chris Dodd 9/17/2022
@FrançoisAndrieux:IS 的结果是一个左值(一种参考)。在许多情况下,该引用可以隐式转换为其他内容(通常是右值),但 a 不是其中之一。*thisdecltype
0赞 François Andrieux 9/17/2022
@ChrisDodd 我不认为这是准确的:timsong-cpp.github.io/cppwp/expr.unary.op#1 左值是一个应用表达式属性的值类别。您可能会将左值(值类别)与左值引用混淆。
2赞 NathanOliver 9/17/2022
@digito_evo 这有很多道理。我从 ~2000 年开始使用 C++,似乎每周我都会学习新东西。我也非常确定我永远不会理解所有的重载解决规则。标准的那部分让我的大脑感到痛苦,光是想想;)

答:

0赞 Chris Dodd 9/17/2022 #1

将一元应用于指针的结果是指向值的引用(左值引用),而不是指向值的副本。因此(或对于任何指针类型)将始终是引用类型。没什么特别的。operator*decltype(*this)decltype(*foo)this

评论

0赞 François Andrieux 9/17/2022
我不认为这那么容易。指针的间接是指“左值引用表达式指向的对象或函数”,这与引用不同。编辑:查看副本。
0赞 Chris Dodd 9/17/2022
“左值”是(只是)C++中的一种引用(还有其他类型的引用)。
0赞 François Andrieux 9/17/2022
左值引用是一种引用。左值表达式是不同的。某些东西可以是没有引用类型的左值表达式。如果我们以后使用表达式,则表达式是左值表达式,不使用任何引用类型。int i = 0;i;
1赞 NathanOliver 9/17/2022
@ChrisDodd 是 中的声明符。它是 中的左值表达式。我的评论中有 2 行代码。fooint foo = 42;foo;
1赞 NathanOliver 9/17/2022
不,它没有。 没有被声明为引用,并且是 ,而不是 : coliru.stacked-crooked.com/a/330c00696e7cfbaffoodecltype(foo)intint&