2012-03-06 22 views
3

私は現在、取得しようとしていますコンパイルするには、次(定数)オーバーロードされたメソッド

class foo { 
}; 

class bar { 
public: 
    const foo & to_foo() const { 
    return f; 
    } 

    foo & to_foo() { 
    return f; 
    } 
private: 
foo f; 
}; 

template< typename T, typename Enable = void > 
class convert {}; 

template< typename T > 
struct convert< T, typename std::enable_if< std::is_member_function_pointer< decltype(&T::to_foo) >::value >::type > { 

    static const foo & call1(const bar & b) { 
    return b.to_foo(); 
    } 

    static foo & call2(bar & b) { 
    return b.to_foo(); 
    } 
}; 

しかし、それが選択されますので、2つの可能性のあるto_foo()メンバーの存在によって混乱専門の取得者デフォルトの場合。 to_foo()メンバーのいずれかを削除するとすぐに機能しますが、callX()メソッドの1つがconstと一致しないため失敗します。

この場合、この機能を検出する方法はありますか?

EDIT:ここ

がideone上の例である:http://ideone.com/E6saX

の方法のいずれかが除去されると、それだけで正常に動作します:http://ideone.com/iBKoN

+1

それはあなたがここで達成しようとしているものを少しは不明だ: を参照してください。あなたが現在解決しようとしていることがわかるように、 'convert'の使い方を説明できる方が良いでしょう。 –

+0

@MatthieuM:これは、より複雑なより大きなフレームワークの一部で、複数のタイプを扱います。いくつかのタイプでは、使用する前に変換が必要です。しかし、私はこれらの変換された型をどのように変換するかを検出する方法が必要です。これは入力型に大きく依存します。与えられたコードは、私が現在仕事に着手しようとしている、これの小さなデッドダウンされた部分です。 – LiKao

答えて

1

それはまだあなたが達成しようとしているものを私に少しは不明です。ターゲットタイプ(foo)が修正され、フルブリッジシステムを作成しようとしていないと仮定します。

この場合、構造を切り離し、過負荷の選択のみに依存することができます。

foo const& to_foo(bar const& b) { return b.to_foo(); } 
foo& to_foo(bar& b) { return b.to_foo(); } 

実際の翻訳が行われる限り、問題なく機能します。関連するテンプレートはありません。

この変換が可能かどうかは、実際にの検出の質問があります。この場合、変換を試みる際にハードエラーを避けるためにSFINAEを使用する必要があります。

#include <iostream> 
#include <utility> 

// Didn't remember where this is implemented, oh well 
template <typename T, typename U> struct same_type: std::false_type {}; 
template <typename T> struct same_type<T, T>: std::true_type {}; 

// Types to play with 
struct Foo {}; 
struct Bar { Foo _foo; }; 
struct Bad {}; 

Foo const& to_foo(Bar const& b) { return b._foo; } 
Foo& to_foo(Bar& b) { return b._foo; } 

// Checker 
template <typename T> 
struct ToFoo { 
    T const& _crt; 
    T& _rt; 

    template <typename U> 
    static auto to_foo_exists(U const& crt, U& rt) -> 
     decltype(to_foo(crt), to_foo(rt), std::true_type()); 

    static std::false_type to_foo_exists(...); 

    // Work around as the following does not seem to work 
    // static bool const value = decltype(to_foo_exists(_crt, _rt))::value; 
    static bool const value = same_type< 
           decltype(to_foo_exists(_crt, _rt)), 
           std::true_type 
          >::value; 
}; 

// Proof 
int main() { 
    std::cout << ToFoo<Bar>::value << "\n"; // true 
    std::cout << ToFoo<Bad>::value << "\n"; // false 
} 

注:成功したとgcc 4.5.1(周りの仕事で)クラン3.0でコンパイル。

+0

ああ、そうです。余分な間接指示は、エラーが発生した場合に役立ちます。今のところ私はただ一つのメソッドの名前をto_foo()からto_const_foo()に強制することでこの問題を解決しました。しかし、これは2つの方法が実際に同じことをするので、より醜いハックです。したがって、同じ名前を持つ必要があります。あなたの方法を採用できるかどうかがわかります。 – LiKao

0

私はについて多くを知りませんテンプレートはまだありますが、機能がconstかどうかを調べるためには、is_constがあなたが探しているタイプの特徴であるようです。

リンクhere

+0

しかし、メソッドがオーバーロードされているため、 'T :: to_foo'は推測できません。オーバーロードされたメソッドの場合、正しい署名への 'static_cast'が必要です。 –

+0

いいえ、is_const'は、メソッドが存在するかどうかを判断しようとしているので、明らかに助けにはなりません。私は後の部分を除いてconstについて本当に気にしない。 'convert'クラスをconstとnon-constnessを処理する部分に分割しなければならないかもしれませんが、これはオーバーロードされたメソッドの存在を検出する問題を解決しません。 – LiKao

-1

私のgcc(4.1.0)はC++ 0xをサポートしていないので、std :: enable_if部分を削除します。コンパイルして正常に実行します。 http://ideone.com/KzasX

おかげ

関連する問題