c++ - 该计划是否违反 ODR?

标签 c++ visual-c++ language-lawyer

考虑这个程序:

#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>(); }
( Compiler Explorer )
各种版本的GCC和Clang都可以接受,但是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 拒绝它?

最佳答案

MSVC 在这里有一个错误。
对于大多数函数,参数的等价性足以指示错误。对于模板,还涉及返回类型表达式。
MSVC 似乎忽略了返回类型表达式,并生成了一个错误,好像它可以忽略它一样。g<T>()/!g<T>()部分可以拆分为sizeof(T)==1sizeof(T)!=1删除另一个混淆特征(事实上,这两个特征之一不能被实例化)。
尝试这个:

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() {}
它将在所有 3 个编译器中工作。

关于c++ - 该计划是否违反 ODR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66755050/

相关文章:

javascript - ECMAScript 规范是否允许 Array 为 "superclassable"?

c++ - 通用打印功能

c++ - 在 std::list 中查找

c++ - 在 cpp 文件中使用#include "Stdafx.h"

c++ - 如何将 DWORD 转换为 wstring?

visual-c++ - "using namespace ...."为什么?

c - C 中 i++ 和 (i)++ 的区别

c++ - 使用 cmake 设置 gsl 时出现问题

c++ - C++11 标准是否要求通过常量 unordered_container 的两次迭代以相同的顺序访问元素?

c - `*`(星号)是 C11 中的关键字吗?