7

我有一个问题,我想提供一个函数的通用版本,该版本foo只能在绝对没有其他匹配的调用时应用。如何修改以下代码,使其与thanlast_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 是一个更好的匹配,因为它不需要转换,不像 base::foo for derived::type()。只有在两个候选者通过参数和可能的转换判断“同样好”的情况下,才首选非模板。

于 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

您可以在声明bar. 这可以在也可以不在。derived::typederived::typenamespace derived

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