简体   繁体   中英

“Emulating” std::declval issues. Works (kind of) in g++, fails to compile in clang++

Trying to better understand std::declval , I came up with the following "toy model" code:

#include <iostream>
#include <typeinfo>

struct Bar
{
    Bar(double);  // some non-default ctor
    double f();   // some function of which return type we want to get
};

using Barref = Bar&&; // emulating std::declval<Bar>()

int main()
{
    // FUNKY, compiles in g++, not in clang++
    // error: unexpected type name 'Barref': expected expression
    decltype(Barref.f()) x; // (1)
    std::cout << typeid(x).name() << std::endl; // i -> int INCORRECT

    // OK, just for testing
    decltype(std::declval<Bar>().f()) y; // (2)
    std::cout << typeid(y).name() << std::endl; // d -> double CORRECT
}

So I'm typedef-ing Barref as a rvalue reference of type Bar&& , and use it in an a decltype expression in (1). If I understand correctly, this is exactly what std::declval does, it is a non-defined function that returns a rvalue reference to its template parameter

template<class T>
typename std::add_rvalue_reference<T>::type declval();

so we can then use the latter in unevaluated contexts, such as decltype . It is useful whenever the type has a non-default ctor, and we'd like to get some type information about some member function without the need to construct the object. Well, that's what I though my code below does. g++5.1 compiles it , but x is of type int (instead of double , as I would have guessed). However, clang++ fails to compile the code , saying

error: unexpected type name 'Barref': expected expression decltype(Barref.f()) x;

My question(s):

  1. Is the code above legal? Is my usage of decltype(Barref.f()) really the same as using decltype(std::declval<Bar>().f()) ? It seems a bit weird, as Barref.f() is not really a return value of a function (even if un-evaluated). I realized that even decltype(Bar.f()) compiles (g++), with no type alias whatsoever.

  2. If the code is legal, why does the type of x is int instead of double ?

Minimized to

struct Meow {};

int main(){
    decltype(Meow.purr()) d;
}

This is plainly invalid code, yet GCC 5.1 and trunk accept it. Not much to say about it other than "bug". Interestingly, both correctly rejects

struct Meow {};
decltype(Meow.purr()) d;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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