7

foo呼び出しに一致するものが他にまったくない場合にのみ適用できる汎用バージョンの関数を提供したいという問題があります。次のコードを変更して、よりもlast_resort::foo一致しないようにするにはどうすればよいですか?の定義を変更する必要がなく、の引数の型を保持する解決策を見つけたいと思います 。derived::typebase::foobarlast_resort::foo

#include <iostream>

namespace last_resort
{

template<typename T> void foo(T)
{
  std::cout << "last_resort::foo" << std::endl;
}

}

template<typename T> void bar(T)
{
  using last_resort::foo;
  foo(T());
}

namespace unrelated
{

struct type {};

}

namespace base
{

struct type {};

void foo(type)
{
  std::cout << "base::foo" << std::endl;
}

}

namespace derived
{

struct type : base::type {};

}

int main()
{
  bar(unrelated::type()); // calls last_resort::foo
  bar(base::type());      // calls base::foo
  bar(derived::type());   // should call base::foo, but calls last_resort::foo instead

  return 0;
}
4

4 に答える 4

3

これはそれが得るのと同じくらい悪いでしょう:

struct badParam { template <typename T> badParam(T t) { } };
namespace last_resort {
  void foo(badParam, int dummy = 0, ...) {
    std::cout << "last_resort::foo" << std::endl;
  }
}

ユーザー定義の変換、デフォルトのパラメーター、および未使用の省略記号があります。

[編集]

わずかなバリエーションですが、保存するためTに、ユーザー定義の変換をダミーパラメーターに移動しました。

struct badParam { 
    badParam() { }
    operator int() { return 42; }
};
namespace last_resort {
  template <typename T> void foo(T t, int dummy = badParam(), ...) {
    std::cout << "last_resort::foo" << std::endl;
  }
}
于 2011-09-30T22:59:12.693 に答える
1

あなたはそれについて多くをすることはできません。両方のfoo関数がオーバーロードセットに含まれています。ただし、last_resortは、derived :: type()のbase :: fooとは異なり、変換を必要としないという理由だけで、より適切に一致します。パラメータと可能な変換から判断して、2つの候補が「同等に良好」である場合にのみ、非テンプレートが推奨されます。

于 2011-09-30T18:42:18.563 に答える
1

last_resort::fooで設定された過負荷から削除できますdisable_if。それ以外の場合は整形式のlast_resort::foo(T)場合は無効にするという考え方です。foo(T)これにより、次last_resort::foo(T)の場合に最悪の一致が発生しfooます。

namespace test
{

template<typename T> struct has_foo { ... };

}

namespace last_resort
{

template<typename T>
  struct disable_if_has_foo
    : std::enable_if<
        !test::has_foo<T>::value
      >
{};

template<typename T>
  typename disable_if_has_foo<T>::type foo(T)
{
  std::cout << "last_resort::foo" << std::endl;
}

}

出力:

$ g++ last_resort.cpp 
$ ./a.out 
last_resort::foo
base::foo
base::foo

この回答fooは、を返す関数()の存在をチェックするためのソリューションを構築する方法を説明していますvoid

于 2011-10-01T05:30:34.120 に答える
0

の宣言の後に、barfor型のオーバーロードを指定できます。これは、含まれる場合と含まれない場合があります。derived::typederived::typenamespace derived

void bar(derived::type)
{
  foo(derived::type());
}
于 2011-09-30T20:40:19.717 に答える