当前位置: 首页 > 知识库问答 >
问题:

这个程序是否违反ODR?

柴意智
2023-03-14

考虑以下程序:

#include <type_traits>

template <typename T> constexpr bool g() { return true; }
template <typename T> std::enable_if_t< g<T>()> f() {}
template <typename T> std::enable_if_t<!g<T>()> f() {}

int main() { f<int>(); }

(编译器资源管理器)

GCC和Clang的各种版本都可以接受它,但MSVC不能接受它,因为MSVC编译失败,出现错误消息

1>D:\x.cpp(5,49): error C2995: 'enable_if<0,void>::type f(void)': function template has already been defined
1>D:\x.cpp(4): message : see declaration of 'f'
1>D:\x.cpp(4,49): error C3861: 'f': identifier not found

第一条错误消息向我暗示了ODR违规--但如果这个程序是格式不良的NDR,我需要帮助理解为什么会这样。我已经检查了标准草案中的temp.over.link,但我不相信我对它的解释是正确的。根据我的理解,程序是可以的,因为这些函数模板有不同的签名。

在不太可能的情况下,这个程序是正确的,为什么MSVC拒绝它?

共有1个答案

汝繁
2023-03-14

MSVC这里有一个bug。

对于大多数函数,参数的等价足以指示错误。对于模板,还涉及返回类型表达式。

MSVC似乎忽略了返回类型表达式,并生成了一个错误,就好像它可以忽略它一样。

template <typename T, std::enable_if_t<g<T>(),bool> =true> void f() {}
template <typename T, std::enable_if_t<!g<T>(),bool> =true> void f() {}
 类似资料:
  • 来自Liskov替代原理-www.blackwasp。co.uk 不符合LSP的一个常见指示是当客户端类检查其依赖项的类型时。这可以通过读取人为描述其类型的对象的属性或通过使用反射来获得类型。通常,根据依赖项的类型,将使用开关语句执行不同的操作。这种额外的复杂性也违反了打开/关闭原则(OCP),因为随着更多子类的引入,客户端类需要修改。 以下技术(使用反射)是否会导致违反LSP? 依赖注入 注:我

  • 我有以下代码: 所以我们知道

  • 问题内容: Liskov替换原理是SOLID的原理之一。我已经读过几次这个原理,并试图理解它。 这就是我的所作所为, 此原则与类层次结构之间的强行为契约有关。子类型应该能够被超类型替换而不会违反合同。 我也读过其他文章,对这个问题我有些失落。难道方法不违反LSP? 上面链接的文章摘录: 换句话说,当通过对象的基类接口使用对象时,用户仅知道基类的前提条件和后置条件。因此, 派生对象不能期望此类用户遵

  • 根据方法<code>java.util.concurrent的约定。未来#取消: 此方法返回后,对 isDone 的后续调用将始终返回 true。 Netty的Future接口扩展了它: 所以Netty应该遵守合同。但事实上Netty没有。您可以运行以下示例代码: 控制台应打印: 真 但实际上它打印: 假 以下方法也违反了合同: 我已经在github上创建了一个问题:问题 但是我仍然想在stack

  • 问题内容: 我遇到了一个项目有两次相同的.jar(对于我来说,是el-api.jar v2.1)两次的问题,因此,当我尝试使用Tomcat 6运行项目时,出现了以下错误堆栈。 我发现了 http://blog.springsource.com/2008/10/20/understanding-the-osgi-uses- directive/ 但这没有用,因为解决方案影响了我项目的太多部分。 我无

  • 如果S是T的一个子类型,那么T类型的对象可以被S类型的对象替换。 子类有两种不同的行为(选中与未选中),在某些情况下,除非更改当前代码,否则无法用子类对象有效地替换基类用法,例如,如果编写如下代码: 这是违反吗?,为什么/为什么不?。 资料来源:http://www.oracle.com/technetwork/articles/entarch/effective-exceptions-09234