18

次のコード:

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 を使用しています

4

6 に答える 6

14

魔法の言葉は次のとおりです。

struct A
{
    int f(int);
    auto g(int x) -> decltype((((A*)0) ->* &A::f)(x)) ;
};

編集Mikael Persson's answer から、これがブーストで行われる方法であることがわかります。

于 2011-02-28T23:06:35.283 に答える
7

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;
}
于 2014-04-30T22:37:19.297 に答える
6

現在、「this」と関数本体内のクラスのメンバーにのみアクセスできますが、これはすぐに変更される可能性があります。

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1207

于 2011-03-01T19:24:50.080 に答える
5

コモー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);
};

基本的に、必要な型を取得する追加の構成を少なくとも 1 つ宣言する必要があります。そしてdecltype直接使う。

編集:ちなみに、これはメンバー関数の戻り値の型に飛び込む場合にもうまく機能します:

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()-> ...少なくともコンパイルされます。

于 2011-02-28T22:35:12.417 に答える
3

いくつかのテストの後、どちら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));
};
于 2011-02-28T21:03:27.263 に答える
0

decltypeがメソッドの外にあり、Aがその時点で不完全な型であるため、機能しないように思われます(したがって、実行することもできませんA().f(x))。

しかし、あなたは本当にそれを必要とすべきではありません。Aの宣言以外では、これは期待どおりに機能します。Aでは、数行上で宣言した関数の戻り型を知っている必要があります。または、次のように書くこともできます。

struct A {
    typedef int ret_type;
    ret_type f(int x);
    ret_type g(int x);
};

これはプレーンなc++03でも機能します。

于 2011-02-28T22:30:38.600 に答える