只有在其他重载失败时才使用模板重载
Only use templated overload when other overloads fail
是否有一种方法可以确保除非所有其他重载都失败,否则不会选择模板重载,而无需求助于enable_if?
Int应该由长重载处理,但它是由模板重载处理的,编译器不喜欢这样。
class SetProxy {
public:
void operator=(const TemplateString& value) {
dict_.SetValue(variable_, value);
}
template<class T>
void operator=(const T& value) {
dict_.SetValue(variable_, TemplateString(value.data(), value.size()));
}
void operator=(long value) {
dict_.SetIntValue(variable_, value);
}
}
为什么int
会由long
重载处理?它们不是同一类型,具有T = int
的模板与int
完全匹配,而long
不是完全匹配。
你能给我们更多关于你试图解决的潜在问题的信息吗?
问题中代码的问题是,如果传递了可转换为long
或TemplateString
的参数,则模板是最佳匹配:模板不需要进行转换,而调用其他函数则需要进行转换。
即使不使用std::enable_if
也可以实现所需的行为,尽管我认为禁止使用std::enable_if
是一个虚构的要求:即使你不能使用C++2011或Boost,实现std::enable_if
也非常简单。实现一些想要的类型特征有点困难,但却是可行的。有效地限制它的使用意味着你需要以一种或多或少做作的方式实现本质上相同的逻辑,但没有说明它真正的作用。例如,此代码不使用std::enable_if
或SFINAE,但实际创建了一个额外的对象,如果使用了SFINAE则不需要该对象:
#include <iostream>
#include <string>
class SetProxy {
template <typename F>
struct helper {
helper(F const& v): value_(v) {}
F const& value_;
};
template<typename F>
void aux(helper<F> value, ...) {
std::cout << "template " << value.value_ << "n";
}
template<typename F>
void aux(long value, int) {
std::cout << "long: " << value << "n";
}
template<typename F>
void aux(std::string const& value, int) {
std::cout << "string: " << value << "n";
}
public:
template<typename T>
void operator=(const T& value) {
this->aux<T>(value, 0);
}
};
struct foo {};
std::ostream& operator<< (std::ostream& out, foo const&) {
return out << "foo";
}
int main()
{
SetProxy p;
p = 17l;
p = 17;
p = foo();
p = "hello";
p = std::string("hello");
}
它没有使用原始问题中的类型,因为我无法访问它们,而且我不想键入与实际问题无关的内容。注意,这有效地包含了std::is_convertible
的实现的重要比特。在内部,有必要转发到另一个模板,因为赋值运算符不能有变量参数列表:由于有从int
到helper<int>
的可行转换,如果没有其他东西来区分类型,就会有歧义,因此使用变量参数列表会使模板版本更差。
仅供参考,在我看来,这是使用std::enable_if
:的可读性更强的版本
class SetProxy {
public:
template <typename T>
typename std::enable_if<!std::is_convertible<T, long>::value
&& !std::is_convertible<T, std::string>::value, void>::type
operator= (T const& value) {
std::cout << "template: " << value << "n";
}
void operator= (long value) {
std::cout << "long: " << value << "n";
}
void operator= (std::string value) {
std::cout << "std::string: '" << value << "'n";
}
};
int与这里的模板版本匹配并不意外。模板参数匹配将获得const int&
的正匹配,并将其传递给重载解析。const int&
比long
更适合int
。如果你想避免为int类型调用模板版本,那么我建议你为int添加一个显式重载。
- 使用模板化运算符重载 XOR 运算符失败
- 重载的 operator() 在 Cython 中失败
- ostream_iterator运算符=在pair<int,int>上失败,但在包装器类上工作。我不能为成对<>重载运算符<<吗?
- 在 if 语句中调用重载构造函数失败
- 可变参数模板函数重载失败
- 模板实例化失败:编译器选择不正确的重载函数
- C++ - 在 std::thread 中调用重载函数时编译失败
- 为什么模板参数推导在重载函数时失败?
- 从类方法调用命名空间中名为 Same 的函数时,重载解析失败
- 线性重载:为什么 clang 在 GCC 编译时失败?
- 运算符 == 重载函数失败
- 模板参数扣除失败因运算符重载而失败
- 具有重载<<运算符的简单模板类失败,"Invalid use of template-id"
- 重载乘法运算符失败
- 运算符重载:正常 MSVS,但在 g++ 中失败
- 运算符 << ,>>特定类的重载失败
- 运算符重载失败,运算符[]和运算符强制转换为int
- 只有在其他重载失败时才使用模板重载
- 参数包列表展开导致可变构造函数重载失败
- 双模板函数重载失败