问题
The following code:
struct A
{
int f(int);
auto g(int x) -> decltype(f(x));
};
Fails to compile with the error:
error: cannot call member function 'int B::f(int)' without object
If I change it to:
struct A
{
int f(int);
auto g(int x) -> decltype(this->f(x));
};
I get another error:
error: invalid use of 'this' at top level
What is wrong with either of these? I am using gcc 4.6
回答1:
Currently you can only access 'this' and members of the class inside the function body, but this is likely to be changed soon:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1207
回答2:
Here are the magic words:
struct A
{
int f(int);
auto g(int x) -> decltype((((A*)0) ->* &A::f)(x)) ;
};
Edit I see from Mikael Persson's answer that this is how it's done in boost.
回答3:
result_of and decltype in combination can give the the return type for a member function
#include <type_traits>
using namespace std;
struct A
{
int f(int i) { return i; }
auto g(int x) -> std::result_of<decltype(&A::f)(A, int)>::type
{
return x;
}
};
int main() {
A a;
static_assert(std::is_same<decltype(a.f(123)),
decltype(a.g(123))>::value,
"should be identical");
return 0;
}
回答4:
Comeau doesn't like auto
as a top level return type, but the following compiles successfully:
template <typename R, typename C, typename A1> R get_return_type(R (C::*)(A1));
struct A
{
int f(int);
decltype(get_return_type(&A::f)) g(int x);
};
Basically, you have to declare at least one additional construct that gets you the type you want. And use decltype
directly.
EDIT: Incidentally, this works fine for diving into the return type of a member function as well:
template <typename R, typename C, typename A1> R get_return_type(R (C::*)(A1));
struct B { int f(int); };
struct A
{
int f(int);
B h(int);
decltype(get_return_type(&A::f)) g(int x);
decltype(get_return_type(&A::h).f(0)) k(int x);
};
int main()
{
return A().k(0);
}
Granted, it doesn't have the same convenience of auto f()-> ...
, but at least it compiles.
回答5:
After some tests, neither decltype(declval<A>().f(x))
nor decltype(((A*)0)->f(x))
will work.
However, it seems that using boost::bind will work (and it's "under-the-hood" version):
struct A
{
int f(int);
auto g(int x) -> decltype(boost::bind(&A::f,0,x)());
auto h(int x) -> decltype((((A*)0)->*(&A::f))(x)); //similarly (what Boost.Bind does under-the-hood.
};
Of course, this is not pretty. I guess you can look into how boost::bind does it to maybe find a nicer solution.
EDIT
As MSN suggested, you can also make your own function template to resolve this:
template< typename R, typename C, typename... Args > R member_func(R (C::*)(Args...));
struct A
{
int f(int);
auto g(int x) -> decltype(member_func(&A::f));
};
回答6:
Seems to me that does not work because the decltype is outside of the method and A is at that moment an incomplete type (so you can't even do A().f(x)
).
But you should not really need that. Outside of the declaration of A this will work as expected, in A you should know the return type of the function that you declared a few lines above. Or you could just write:
struct A {
typedef int ret_type;
ret_type f(int x);
ret_type g(int x);
};
This even works with plain c++03.
来源:https://stackoverflow.com/questions/5147492/member-function-call-in-decltype