为什么C++找不到布尔运算符,当有一个!范围内的运算符?

Why does C++ not find bool operator when there's a ! operator in scope?

本文关键字:运算符 范围内 有一个 C++ 找不到 布尔 为什么      更新时间:2023-10-16

正在处理解析器组合器库,这个例子就是从这个库派生出来的,尽管显然一些名称已经更改以保护无辜者:

#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 是字符串时替换,而另一个类型上有一个布尔运算符。 如果我尝试调用 !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;
}

这样,如果编译器尝试选择此函数,它将无法将参数替换为签名并忽略它。这不会发生在函数的主体中,这就是您的版本失败的原因。