内联模板函数由于if constexpr而具有不同的行为,这是否违反了ODR



可以检测类型是否完整https://devblogs.microsoft.com/oldnewthing/20190710-00/?p=102678

如果一个类型是完整的,我有理由想要提供一个不同的(可内联的(实现。

模板化函数在基于函数中if constexpr的不同转换单元中表现不同是否违反ORD?从某种意义上说;相同的";函数(不是宏在C++源级别创建不同的定义,这违反了ODR(。

这里有一个简单的例子:

#include <iostream>
#include <type_traits>

// From https://devblogs.microsoft.com/oldnewthing/20190710-00/?p=102678
template<typename, typename = void>
constexpr bool is_type_complete_v = false;
template<typename T>
constexpr bool is_type_complete_v
<T, std::void_t<decltype(sizeof(T))>> = true;

template <typename T>
T* loggingGetRef(T* x) {
if constexpr (is_type_complete_v<T>) {
std::cout << "Complete!" << std::endl;
} else {
std::cout << "Incomplete!" << std::endl;
}
return x;
}
struct S
//{} // <- Uncomment this to make loggingGetRef be "different" through if constexpr.
;
int main() {    
S* ptr = nullptr;
loggingGetRef(ptr);    
}

https://godbolt.org/z/q1soa58PY

对于我的应用程序,我希望两个if constexpr分支在外观上表现相同(与打印不同内容的示例不同(,因此从正确性的角度来看,如果链接器为任何一个实现选择程序集并在任何地方使用它,那也没问题。只是在T完成的翻译单元中,我们可能能够获得更好的性能(我完全希望它是内联的(。

ODR不是基于"模板化函数";;它基于实际函数。模板基于模板参数生成函数。每个唯一的模板参数集代表一个不同的函数。从同一模板生成的不同函数是不同的函数。无论是什么创建了不同的函数,它们之间都没有ODR期望值。

loggingGetRef<S>是特定函数的名称。如果您所做的某些操作导致loggingGetRef<S>由于常量表达式而产生不同的生成,则表示您的代码格式不正确(不需要诊断(。但这不是违反网上解决的问题;这违反了模板实例化的规则。用一组特定参数实例化的模板在用这些参数实例化它的所有转换单元中必须是相同的。时期

相关内容

  • 没有找到相关文章