gpt4 book ai didi

c++ - 如果方法不进行类型检查,为什么 C++ 模板会匹配?

转载 作者:可可西里 更新时间:2023-11-01 17:55:35 26 4
gpt4 key购买 nike

以下代码无法编译,因为结构 A 不支持 -- 运算符。

struct A {};

struct B {
void Run() {}
A& Dec(A& a) { return --a; }
};

int main(int argc, char** argv) {
B b;
b.Run();
}

与此代码相同。

struct A {};

template <class T>
struct B {
void Run() {}
A& Dec(A& a) { return --a; }
};

int main(int argc, char** argv) {
B<A> b;
b.Run();
}

那么为什么要编译(在 C++11 中)?

struct A {};

template <class T>
struct B {
void Run() {}
T& Dec(T& a) { return --a; }
};

int main(int argc, char** argv) {
B<A> b;
b.Run();
}

看起来实例化模板不会自动实例化模板中未使用的方法,这些方法依赖于要进行类型检查的类型参数,这意味着即使模板的某些方法不匹配,模板也会匹配。这是令人失望的,因为我希望使用 SFINAE 来检测各种方法和运算符对类型的适用性,但如果模板替换成功,即使调用这些方法会出现编译时错误,该技术也不会起作用。

最佳答案

(由 C++ 委员会决定)模板类的方法只有在使用时才会实例化它们的主体。

这使得编写一些 C++ 代码变得更容易,但在使用时会出现硬错误。

例如,std::vectorstd::vector::operator< 一起使用;如果你没有 <调用它是一个错误。如果这样做,调用它就有效。

更现代的 C++ 会鼓励 SFINAE 禁用它,这样你就可以检测到是否 <是否安全,但在 std::vector 时并未使用该技术被设计。您可以在 std::function 中看到此技术使用的演变。 ,从贪婪地消耗通用构造函数中的几乎所有内容,到该构造函数仅在 C++11 和 C++14 之间工作时才被考虑用于重载决议。

如果您想要 SFINAE,您不能依赖那样的代码主体。为了减轻编译器的负担,编译器在进行 SFINAE 测试时只需检查声明而不是函数定义。

部分原因是SFINAE在表达式上很难;在整个 body 上更难。编译器必须推测性地编译函数体,遇到错误,然后返回到“不,什么都没做”状态。

函数体中的错误总是硬错误。在当前版本的 C++ 中,您无法避免这一点。

现在,您可以编写决定是否有错误但实际上没有错误的函数,然后使用它们的主体来确定其他代码是否会出错。例如:

template<class T>
auto foo() {
constexpr if(sizeof(T)<4) {
return std::true_type{};
} else {
return std::false_type{};
}

你可以使用foo<char>()在某个 SFINAE 的某个地方,它的 truefalse -ness 可以使另一个重载替换失败或不失败。

请注意,错误(如果有的话)仍然发生在函数体的外部(此处为 foo)。

关于c++ - 如果方法不进行类型检查,为什么 C++ 模板会匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45150007/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com