c++ - 为什么 C++ 在有 !范围内的运营商?

标签 c++ c++11 templates

正在处理一个解析器组合器库,这个例子是从它派生的,虽然显然一些名字已经被更改以保护无辜者:

#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/

相关文章:

c++ - 在其他函数体内声明函数方法的用例是什么?

c++ - 这些编译器之间有什么区别吗?

c++ - "replaced"变量何时不再可寻址

c++ - 这是 "Tag Dispatching"吗?

c++ - undefined reference 、模板结构和 constexpr 静态成员

c++ - 数组类型的模板代码中如何计算 std::size_t

c++ - 如何确定将哪种类型传递给模板定义的函数?

c++ - 将指针传递给结构,对比传递 void 指针并强制转换为结构

c++ - 哪些 C/C++ 函数最常被错误使用并可能导致缓冲区溢出?

c++ - 在 C++11 中传递具有未指定参数的函数?