我有一个问题,我想提供一个函数foo
的泛型版本,只有在调用绝对没有其他匹配时才能应用。如何修改以下代码,使last_resort::foo
与derived::type
的匹配程度低于base::foo
?我想找到一个解决方案,它不涉及修改bar
的定义,而是保留last_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;
}
答案 0 :(得分:2)
这就差不多了:
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;
}
}
答案 1 :(得分:1)
你无能为力。两个foo函数都在重载集中。但是你的last_resort是一个更好的匹配,因为它不需要像gen :: type()的base :: foo那样的转换。只有在两个候选人根据参数和可能的转换判断“同样好”的情况下,才会使用非模板。
答案 2 :(得分:0)
在声明bar
后,您可以为derived::type
类型提供derived::type
的重载。这可以是namespace derived
或不是。
void bar(derived::type)
{
foo(derived::type());
}
答案 3 :(得分:0)
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
This answer描述了如何构建解决方案,以检查是否存在返回foo
的函数(void
)。