Get return type of member function without an object
You don't need that- remember that since decltype doesn't evaluate its argument, you can just call on nullptr
.
decltype(((T*)nullptr)->foo()) footype;
decltype as a return type in class member function
The definition of the class
is processed it two passes: first the member declarations are collected, including function signatures, and then the bodies of definitions are parsed.
The function body therefore has access to all member declarations, including subsequent ones, but the function prototype only sees preceding declarations.
How to get the return type of a member function from within a class?
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)());
}
Deduce return type of member function
Is this close to what you wanted?
#include <vector>
#include <utility>
#include <memory>
struct Foo
{
int member_func();
};
template <typename Vec>
void func(const Vec& vec) {
using ret_type = decltype(std::declval<typename Vec::value_type>()->member_func());
std::vector< ret_type > local_vec;
}
int main()
{
std::vector<std::unique_ptr<Foo>> v;
func(v);
}
Demo: https://godbolt.org/g/dJkSf1
Explanation:
std::declval<typename Vec::value_type>()
generates a reference to a unique_ptr (which must be used in an unevaluated context). We then take the decltype of calling generated_reference->member_function()
.
This would be the same type as the result of vec[0]->member_func()
Indeed, we could write it this way:
template <typename Vec>
void func(const Vec& vec) {
using ret_type = decltype(vec.at(0)->member_func());
std::vector< ret_type > local_vec;
}
Which might be more expressive and generic (Vec
may now be any type which is vector-like and holds pointer-like things to Foo
)
Furthermore, the more generically we approach the deduction, the more generic our func
function becomes:
#include <vector>
#include <utility>
#include <memory>
#include <set>
#include <iterator>
struct Foo
{
int member_func();
};
template <typename Vec>
void func(const Vec& vec) {
using ret_type = decltype((*std::begin(vec))->member_func());
std::vector< ret_type > local_vec;
}
int main()
{
std::vector<std::unique_ptr<Foo>> v;
func(v);
func(std::array<std::unique_ptr<Foo>, 10> { });
Foo* foos[] = { nullptr, nullptr };
func(foos);
func(std::set<std::shared_ptr<Foo>, std::owner_less<>> {});
}
Note
This code assumes that the return_type of Foo::member_func
is not a reference type.
If that's a possibility, we'd need to decide whether we used metaprogramming to:
a) convert reference types to std::reference_wrapper, so they can be stored in a vector, or
b) convert reference types to fundamental types using std::decay
, which would result in copies being made.
Get the size of the return type of a member function
invoke_result
is defined as:
template< class F, class... ArgTypes>
class invoke_result;
Hence, this is working
return sizeof(std::invoke_result_t<decltype(&QString::ucs2), QString>);
std::bind works with decltype type of class member functions failed
There are a number of issues with your last std::bind
call:
std::remove_pointer(result3)
remove_pointer
is a class. You want remove_pointer_t
which will produce the type sans pointer in parentheses, which leads to the next point
result3
is an instance ofResult*
, we need to usedecltype
to get its type, becauseremove_pointer
operates on type, which leads to the next point:std::remove_pointer
as a templated type trait wants a type as a template argument in angle braces, not in parentheses
With the edits applied this bring us to the following syntax
MyGet mg3 = std::bind(&std::remove_pointer_t<decltype(result3)>::get, result3, std::cref("result3"));
Demo
In the end, a lambda may be easier to deal with. You don't need to construct a std::function
at all:
Result result1;
auto mg1 = [&result1](){return result1.get("result1");};
std::cout << mg1() << std::endl;
Result result2;
auto mg2 = [&result2](){return result2.get("result2");};
std::cout << mg2() << std::endl;
Result* result3 = new Result;
auto mg3 = [result3](){return result3->get("result3");};
std::cout << mg3() << std::endl;
delete result3;
Lambda demo
I highly recommend STL's CppCon 2015 talk about why bind()
is all but deprecated in favor of lambdas.
Deduce member function return type using a class member function object
I have been troubled for hours or days around such problems. Typically gcc wants this->
but clang does not. In some cases Foo::
also helps but there have been cases where I have given up using the member names. The following is only using the type names and (though more verbose) I think will not have any problems with either:
template<typename Base, typename Acc>
struct Foo
{
Base base;
Acc acc;
template<typename S>
using result = typename std::result_of<S>::type;
auto operator()(unsigned i) const
-> result<const Acc(result<const Base(unsigned)>)>
{ return acc(base(i)); }
};
More generally, whenever decltype(member_name)
is causing problems, you can safely use decltype(std::declval<member_type>())
where member_type
is const
-qualified if the member function using it is const
.
Even more generally, if you have a member function that is &&
, &
or const&
qualified, use member_type
, member_type&
or const member_type&
respectively in such expressions.
I have never looked into what the standard says but in practice compilers treat expressions differently in trailing return types and inside function definitions when it comes to class members.
How do I know the actual type and size of the return type of a non-static method in C++?
The decltype specifier needs to be given a legal expression - something you could use in actual code. So you can create an instance and call the member on that instance like this:
decltype(std::vector<int>().size())
It is the same for the sizeof operator. It needs to receive a legal expression.
Related Topics
How to Generate Thread-Safe Uniform Random Numbers
What Is Return Type of Assignment Operator
Converting Float Values from Big Endian to Little Endian
Why Does Visual Studio 2013 Error on C4996
Skipping Incompatible Libraries at Compile
Math to Convert Seconds Since 1970 into Date and Vice Versa
How to Extract the Source Filename Without Path and Suffix at Compile Time
Are There Any Tricks to Use Std::Cin to Initialize a Const Variable
How to Initialize 3D Array in C++
How to Create My Own Ostream/Streambuf
Initializing a Union with a Non-Trivial Constructor
The Implementation of Std::Forward
No Default Constructor Exists for Class X (Inheritance) C++
How Often Should I Call Srand() in a C++ Application
C++ - Decimal to Binary Converting