2012-01-26 12 views
6

このanswerでは、decltype式の一部として、末尾の戻り値の型にというクラスの属性とクラス_argの属性を使用すると意味がありました。それがなくても可能ですが、不便です。メンバ関数の戻り型の末尾にこれと属性を使用しますか?

clang 3.0(下記参照)もgcc 4.5.2も受け付けていません。

#include <iostream> 

class MyClass { 
public: 
    MyClass(int i): _arg(i) {} 

    template <typename F> 
    auto apply(F& f) -> decltype(f(_arg)) { 
    return f(_arg); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _arg)) { 
    return f(*this, _arg); 
    } 

private: 
    int _arg; 
}; 

struct Id { 
    template <typename V> 
    V operator()(V v) const { return v; } 
}; 

struct ComplexId { 
    template <typename C, typename V> 
    V operator()(C const&, V v) { return v + 1; } 
}; 

int main() { 
    Id id; ComplexId complex; 

    MyClass c(0); 

    std::cout << c.apply(id) << " " << c.apply(complex) << "\n"; 
} 

打ち鳴らす3.0は言う:

$ clang++ -std=c++11 -Weverything test.cpp 
test.cpp:8:38: error: use of undeclared identifier '_arg' 
     auto apply(F& f) -> decltype(f(_arg)) { 
            ^
test.cpp:8:45: error: type name requires a specifier or qualifier 
     auto apply(F& f) -> decltype(f(_arg)) { 
              ^
test.cpp:8:45: error: C++ requires a type specifier for all declarations 
     auto apply(F& f) -> decltype(f(_arg)) { 
          ~~~~~~~~  ^
test.cpp:8:7: error: 'auto' return without trailing return type 
     auto apply(F& f) -> decltype(f(_arg)) { 
    ^
test.cpp:13:39: error: invalid use of 'this' outside of a nonstatic member function 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
            ^
test.cpp:13:52: error: type name requires a specifier or qualifier 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
               ^
test.cpp:13:52: error: C++ requires a type specifier for all declarations 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
          ~~~~~~~~    ^
test.cpp:13:7: error: 'auto' return without trailing return type 
     auto apply(F& f) -> decltype(f(*this, _arg)) { 
    ^
8 errors generated. 

ハム...それほど大きくありません。

しかし、C++ 11のサポートはほとんどのコンパイラでは最高のハックですが、Standard(n3290)に記載されている特定の制限が見つかりませんでした。コメントで

、XEOは、それが標準の欠陥であったかもしれないことを示唆...

ので、これを許可するかではないでしょうか?

ボーナス:clang/gccの最新バージョンでこれをサポートしていますか?

+0

Clang 3.1 HEADは同じエラーを吐き出します。 – Xeo

+0

GCC 4.7での同様のエラー。 –

+0

Btw、私は[この興味深い、同様の質問](http://stackoverflow.com/q/7255379/500104)を見つけました。また、@Johannesがメンバーを前もって宣言することを提案して、私はClang 3.1 HEADの '_arg'についてではなく、末尾の戻り型で' this'についてのエラーを得るだけです。 – Xeo

答えて

9

私は忘れてしまった。それはa defect at some pointでしたが、最終的にはresolved and voted into the FDISでした。任意間

§5.1.1 [expr.prim.general]

宣言は、クラスXのメンバ関数またはメンバ関数テンプレートを宣言する場合、式thisタイプのprvalueある「ポインタCV-修飾子-配列にX CV-配列修飾子、および関数定義メンバ宣言子、又は宣言の終わり。

このように、ClangとGCCはまだ正しく実装していません。

struct X{ 
    // 'this' exists between the | markers 
    void f() const volatile | { 
    } | 
    auto g() const volatile | -> void { 
    } | 
}; 
1

あなたが書いたものが合法であるかどうかは知りませんが、あなたが望むものを達成するための他のいくつかの方法があります:

template <typename F> 
    auto apply(F& f) -> decltype(f(*(MyClass*)0, (int)0)) { 
    return f(*this, _arg); 
    } 

または:

template <typename F> 
    typename std::result_of<F(MyClass,int)>::type apply(F& f) { 
    return f(*this, _arg); 
    } 
+0

私がリンクしている答えでは、もっと冗長な形が与えられています。評価されていないコンテキストで 'std :: declval 'が存在することに注意してください。ヌルポインタのトリックは必要ありません:) –

5

あなたのコードはは無効です。クラスがメンバー関数の戻り値の型では完全ではないと考えられるためです。以前に宣言されたメンバーにのみアクセスできます。はいthisを使用してC++ 11末尾の戻り値の型内で有効である、というように

class MyClass { 
private: 
    int _arg; 

public: 
    MyClass(int i): _arg(i) {} 

    template <typename F> 
    auto apply(F& f) -> decltype(f(_arg)) { 
    return f(_arg); 
    } 

    template <typename F> 
    auto apply(F& f) -> decltype(f(*this, _arg)) { 
    return f(*this, _arg); 
    } 
}; 

モデューロのように。

+0

ああ、それは面白いです。私はそれについて考えていませんでしたが、正しいことを思い出すと、同じことが型にも当てはまります(つまり、クラスでも使用する前に宣言する必要がある)。 –

+0

メンバ関数本体内にクラスが完全であるとみなされません。後で宣言されたメンバ型でさえも表示されます。 –

+0

私は[this](http://ideone.com/T1ZS8)について具体的に考えていました: 'struct A {type foo(); typedef int型。 }; '。 *古いスタイルの*解析であると私はいつも悩ましました:x –

関連する問題