首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果方法不进行类型检查,为什么C++模板会匹配?

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

Stack Overflow用户
提问于 2017-07-18 01:11:32
回答 1查看 406关注 0票数 8

因为struct A不支持--运算符,所以下面的代码无法编译。

代码语言:javascript
运行
复制
struct A {};

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

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

这段代码也是如此。

代码语言:javascript
运行
复制
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中)呢?

代码语言:javascript
运行
复制
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来检测各种方法和运算符对类型的适用性,但是如果模板替换成功,即使对方法的调用是编译时错误,该技术也不会起作用。

EN

回答 1

Stack Overflow用户

发布于 2017-07-18 01:34:11

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

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

例如,std::vector将其与std::vector::operator<一起使用;如果没有<调用它,则是错误的。如果你这样做了,调用它是可行的。

更现代的C++会鼓励禁用它,这样您就可以检测<是否安全,但是在设计std::vector时并没有使用这种技术。您可以看到这种技术在std::function中的使用的演变,从贪婪地使用通用构造函数中的几乎任何东西到只有在C++11和C++14之间工作时才考虑重载解析的构造函数。

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

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

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

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

代码语言:javascript
运行
复制
template<class T>
auto foo() {
  constexpr if(sizeof(T)<4) {
    return std::true_type{};
  } else {
    return std::false_type{};
}

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

注意,错误(如果有)仍然发生在函数体之外(这里是foo)。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45150007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档