2017-01-15 1 views
5

関数(グローバル関数またはメンバ関数のいずれか)はそのパラメータでのみオーバーロードされる(そのオーバーロードは常にconstまたはすべてconstでないようにする) 。指定されたパラメータに従って過負荷アドレスを選択するテンプレートを作成する方法はありますか?たとえば:パラメータでオーバーロードアドレスを見つける

struct Foo { 
    double bar(double n, double m); 
    int bar(int n, int m); 
}; 

auto addressDouble = find_overload<&Foo::bar, double, double>::address; 
auto addressInt = find_overload<&Foo::bar, int, int>::address; 

は、私が見つけた面白い答えはhereですが、残念ながらそれだけで右のオーバーロードへの呼び出しを転送し、それが後で使用できるように、実際に過負荷アドレスを取得しませ扱います。

最後の注意:完璧なソリューションは、リリースされたClangバージョンで動作するはずです。この要件とは別に、使用可能なC++ 1z以下の機能を使用できます。

答えて

1

あなたはあなたがしなければならないのバージョンを指定する必要があり、オーバーロード関数のアドレスにアクセスする前に。

template<typename ...TA> 
struct find_overload 
{ 
    template<typename TObj, typename TR> 
    using member_func_t = TR(TObj::*)(TA...); 

    template< typename TObj, typename TR > 
    static constexpr auto get_address(member_func_t<TObj, TR> func) -> member_func_t<TObj, TR> 
    { 
     return func; 
    } 
}; 

int main() 
{ 
    constexpr auto address = find_overload<double, double>::get_address(&Foo::bar); 
} 
+0

_これはグローバル関数またはメンバ関数_です。その答えは、自由な機能の必要性に対処していません。 – skypjack

+0

@skypjackはい、それは無料の機能に対処しませんが、ここでの主な目的は、その実装方法についての基本的な考え方を提供することです。 OP自身が要件を満たすために提供されたソリューションを変更して拡張することができます – MRB

+0

私はダウン投票の理由はありません。下投票のための説明を提供する方が良いです。 – MRB

0

あなたはstatic_cast<>()を使用することができます。

auto addressDouble = static_cast<double(*)(double, double)>(&Foo:bar); 
auto addressInt = static_cast<int(*)(int, int)>(&Foo:bar); 
+0

残念なことに、 'static_cast'を使用するには、私が回避しようとしていた関数の戻り値の型を指定する必要があります。 –

0

@ MMRBのworking answerにもかかわらず、よりコンパクトな解決策が存在する。
それは、最小限の作業例を次に示します。

#include<iostream> 

struct Foo { 
    double bar(double n, double m) {} 
    int bar(int n, int m) {} 
}; 

double quux(double n, double m) {} 
int quux(int n, int m) {} 

template<typename... A, typename T, typename R> 
constexpr auto find_overload(R(T::*f)(A...)) { return f; } 

template<typename... A, typename R> 
constexpr auto find_overload(R(*f)(A...)) { return f; } 

int main() { 
    auto fooAddressDouble = find_overload<double, double>(&Foo::bar); 
    auto fooAddressInt = find_overload<int, int>(&Foo::bar); 
    Foo foo; 
    (foo.*fooAddressDouble)(0., 0.); 
    (foo.*fooAddressInt)(0, 0); 

    auto globalAddressDouble = find_overload<double, double>(&quux); 
    auto globalAddressInt = find_overload<int, int>(&quux); 
    globalAddressDouble(0., 0.); 
    globalAddressInt(0, 0); 
} 

あなたが見ることができるように、find_overloadは無料の機能と(それがクラス型だけでなく、戻り値の型を推論いる)メンバ関数の両方を受け入れます。

+0

自由な関数にもかかわらず、メンバ関数または自由関数の 'const'オーバーロードも考慮する必要があります。 – MRB

+0

@MRB OPは実際には質問で何か違うと言った。 – skypjack

関連する問題