6

SFINAE を使用して、特定のクラスに対してフリー関数がオーバーロードされているかどうかを検出する方法はありますか?

基本的に、私は次の解決策を持っています:

struct has_no_f { };

struct has_f { };

void f(has_f const& x) { }

template <typename T>
enable_if<has_function<T, f>::value, int>::type call(T const&) {
    std::cout << "has f" << std::endl;
}

template <typename T>
disable_if<has_function<T, f>::value, int>::type call(T const&) {
    std::cout << "has no f" << std::endl;
}

int main() {
    call(has_no_f()); // "has no f"
    call(has_f()); // "has f"
}

call実際には多くのfooandbar型があり、関数はそれらを認識していないため、単純なオーバーロードは機能しませんcall(基本的callに a 内にあり、ユーザーが独自の型を提供します)。

私は C++0x を使用できません。最新のすべてのコンパイラに対応するソリューションが必要です。

注: 残念ながら、同様の質問に対する解決策はここでは機能しません。

4

2 に答える 2

3

許可されている場合boost、次のコードが目的に合う可能性があります。

#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;

// user code
struct A {};
static void f( A const& ) {}
struct B {};


// code for has_f
static void f(...); // this function has to be a free standing one

template< class T >
struct has_f {
  template< class U >
  static char deduce( U(&)( T const& ) );

  template< class U, class V >
  static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type
  deduce( U(&)( V const& ) );

  static char (&deduce( ... ))[2];

  static bool const value = (1 == sizeof deduce( f ));
};

int main()
{
  cout<< has_f<A>::value <<endl;
  cout<< has_f<B>::value <<endl;
}

ただし、厳しい制限があります。
このコードは、すべてのユーザー関数に署名があることを前提としている( T const& )ため、( T )許可されていません。
上記の機能void f(...)は自立機能である必要があるようです。
コンパイラが通常どおり2フェーズのルックアップを実行する場合、おそらくすべてのユーザー関数がhas_fクラステンプレートの定義の前に表示される必要があります。
正直なところ、私はコードの有用性に自信がありませんが、とにかくこれが役立つことを願っています。

于 2011-01-26T19:15:17.837 に答える
3
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
#include <type_traits>

struct X {};
struct Y {};

__int8 f(X x) { return 0; }
__int16 f(...) { return 0; }

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) {
    std::cout << "In call with f available";
    f(t);
    return 0;
}

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) {
    std::cout << "In call without f available";
    return 0;
}

int main() {
    Y y; X x;
    call(y);
    call(x);
}

f() の戻り値の型を簡単に変更すると、従来の SFINAE ソリューションが得られます。

于 2011-01-26T15:17:24.537 に答える