Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the return type of a member function from within a class?

The following program yields a compilation error with clang, though it passes on other compilers:

#include <utility>

struct foo
{
  auto bar() -> decltype(0)
  {
    return 0;
  }

  using bar_type = decltype(std::declval<foo>().bar());
};

int main()
{
  return 0;
}

clang yields:

$ clang -std=c++11 clang_repro.cpp 
clang_repro.cpp:10:48: error: member access into incomplete type 'foo'
  using bar_type = decltype(std::declval<foo>().bar());
                                               ^
clang_repro.cpp:3:8: note: definition of 'foo' is not complete until the closing '}'
struct foo
       ^
1 error generated.

Is this program illegal, and if so, is there a correct way to define foo::bar_type?

clang details:

$ clang --version
Ubuntu clang version 3.5-1ubuntu1 (trunk) (based on LLVM 3.5)
Target: x86_64-pc-linux-gnu
Thread model: posix
like image 268
Jared Hoberock Avatar asked Oct 18 '14 00:10

Jared Hoberock


People also ask

What is the return type of member function?

Member Function Return Types. A public member function must never return a non-const reference or pointer to member data. A public member function must never return a non-const reference or pointer to data outside an object, unless the object shares the data with other objects.

How do you find the member function of a class?

Accessing data members and member functions: The data members and member functions of class can be accessed using the dot('. ') operator with the object.

Can the return type of a function be a class?

Absolutely, this is possible. This is also quite common - for example, Factory Method pattern can be implemented within a single class, in which case member functions would be returning instances of the class of which they are members.

Can be used to access the member function of a class?

Explanation: The member functions can be called using only the dot operator or the arrow operator.


1 Answers

g++4.9 issues the same error

I'm not sure if this is an invalid code, because incomplete types are allowed for declval, and expression in decltype is not evaluated.
rightføld in his answer explained very good why this code is invalid.

You can use std::result_of:

using bar_type = std::result_of<decltype(&foo::bar)(foo)>::type;

Which is actually implemented like this:

using bar_type = decltype((std::declval<foo>().*std::declval<decltype(&foo::bar)>())());

The difference between this and the code in the question is that pointer-to-member operator (.*) is used instead of member access operator (.), and it doesn't require the type to be complete, which is demonstrated by this code:

#include <utility>
struct foo;
int main() {
    int (foo::*pbar)();
    using bar_type = decltype((std::declval<foo>().*pbar)());
}
like image 115
Anton Savin Avatar answered Oct 12 '22 12:10

Anton Savin