Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does decltype(*this) not return the correct type?

The following code was compiled with VC++ Nov 2012 CTP. But the compiler gave a warning.

I just wonder whether this is a bug of VC++ Nov 2012 CTP.

struct A
{
    int n;

    A(int n)
        : n(n)
    {}

    int Get() const
    {
        return n;
    }

    int Get()
    {
        //
        // If using "static_cast<const A&>(*this).Get();" instead, then OK.
        //
        return static_cast<const decltype(*this)&>(*this).Get(); // Warning!
    }
};

int main()
{
    A a(8);

    //
    // warning C4717: 'A::Get' : recursive on all control paths,
    // function will cause runtime stack overflow
    //
    a.Get(); 
}
like image 391
xmllmx Avatar asked Feb 28 '13 10:02

xmllmx


People also ask

What does decltype return?

decltype returns If what we pass to decltype is the name of a variable (e.g. decltype(x) above) or function or denotes a member of an object ( decltype x.i ), then the result is the type of whatever this refers to. As the example of decltype(y) above shows, this includes reference, const and volatile specifiers.

What does decltype do in C++?

The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a template function whose return type depends on the types of its template arguments.

Does decltype evaluate expression?

The following expressions do not evaluate their operands: sizeof() , typeid() , noexcept() , decltype() , and declval() .

What does decltype stand for?

Decltype keyword in C++ Decltype stands for declared type of an entity or the type of an expression. It lets you extract the type from the variable so decltype is sort of an operator that evaluates the type of passed expression. SYNTAX : decltype( expression )


1 Answers

decltype applied to an expression that's not an id-expression gives you a reference, so decltype(*this) is already A&, and you can't make that const again. If you really wanted to use decltype, you could do something like this:

static_cast<std::decay<decltype(*this)>::type const &>(*this)

Or even this:

static_cast<std::add_lvalue_reference<
                 std::add_const<
                      std::decay<decltype(*this)>::type
                 >::type
            >::type
>(*this)

Of course it's much simpler to just say static_cast<A const &>(*this).

like image 110
Kerrek SB Avatar answered Sep 29 '22 00:09

Kerrek SB