Ответ 1
В настоящее время вы можете получить доступ только к 'this' и к членам класса внутри, но это скорее всего скоро изменится:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1207
Следующий код:
struct A
{
int f(int);
auto g(int x) -> decltype(f(x));
};
Не удается скомпилировать с ошибкой:
error: cannot call member function 'int B::f(int)' without object
Если я изменил его на:
struct A
{
int f(int);
auto g(int x) -> decltype(this->f(x));
};
Я получаю еще одну ошибку:
error: invalid use of 'this' at top level
Что не так с этим? Я использую gcc 4.6
В настоящее время вы можете получить доступ только к 'this' и к членам класса внутри, но это скорее всего скоро изменится:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1207
Вот волшебные слова:
struct A
{
int f(int);
auto g(int x) -> decltype((((A*)0) ->* &A::f)(x)) ;
};
Изменить. Я вижу, что от Микаэля Перссона отвечает, что так оно и есть в boost.
result_of и decltype в комбинации могут дать возвращаемый тип для функции-члена
#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;
}
Comeau не нравится auto
как тип возврата верхнего уровня, но следующие компиляции успешно:
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);
};
В принципе, вы должны объявить хотя бы одну дополнительную конструкцию, которая получит нужный вам тип. И используйте decltype
напрямую.
EDIT: Кстати, это отлично подходит для погружения в возвращаемый тип функции-члена:
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);
}
Конечно, он не имеет того же удобства auto f()-> ...
, но, по крайней мере, компилируется.
После некоторых тестов не будет работать ни decltype(declval<A>().f(x))
, ни decltype(((A*)0)->f(x))
.
Однако, похоже, что использование boost:: bind будет работать (и это "под капотом" ):
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.
};
Конечно, это некрасиво. Я думаю, вы можете посмотреть, как boost:: bind делает это, возможно, более приятным решением.
ИЗМЕНИТЬ
Как предположил MSN, вы также можете создать свой собственный шаблон функции, чтобы решить эту проблему:
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));
};
Мне кажется, что это не работает, потому что decltype находится вне метода, и A в данный момент является неполным (поэтому вы даже не можете сделать A().f(x)
).
Но вам это не нужно. Вне декларации A это будет работать так, как ожидалось, в вы должны знать тип возврата функции, которую вы объявили несколькими строками выше. Или вы можете просто написать:
struct A {
typedef int ret_type;
ret_type f(int x);
ret_type g(int x);
};
Это даже работает с простым С++ 03.