正在处理一个解析器组合器库,这个例子是从它派生的,虽然显然一些名字已经被更改以保护无辜者:
#include <string>
#include <stdio.h>
using namespace std;
template <typename T> struct only_string;
template <> struct only_string<string> {};
struct another_type {
explicit operator bool() const { return true; }
};
// only substitute if T is string
template <typename T>
bool operator !(T) {
only_string<T> a;
return true;
}
int main() {
another_type a;
if (!a) {
return 1;
} else {
return 0;
}
}
我有一个模板运算符!应该只在 T 是字符串时替换,而另一种类型上有 bool 运算符。如果我尝试调用 !a,它会先找到运算符,替换失败并放弃。任何人都可以解释这种行为以及如何纠正它吗?
这是 g++ 5.4.0 的输出
> g++ -std=c++11 test.cc -o test
test.cc: In instantiation of ‘bool operator!(T) [with T = another_type]’:
test.cc:24:10: required from here
test.cc:17:20: error: ‘only_string<another_type> a’ has incomplete type
only_string<T> a;
^
最佳答案
是的,编译器“放弃”了,因为它认为 !运算符是最佳匹配。如果您真的希望编译器忽略该重载,则需要使用一种称为 SFINAE 的技术。
template <typename T,
std::enable_if_t<std::is_same_v<T, std::string>>* = nullptr>
bool operator !(T) {
return true;
}
那样的话,如果编译器试图选择这个函数,它将无法将参数替换到签名中并忽略它。这不会发生在函数体中,这就是您的版本失败的原因。
关于c++ - 为什么 C++ 在有 !范围内的运营商?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50396403/