[英]Is it an ODR violation to have an inline templated function have different behavior due to if constexpr?
It's possible to detect if a type is complete https://devblogs.microsoft.com/oldnewthing/20190710-00/?p=102678可以检测类型是否完整https://devblogs.microsoft.com/oldnewthing/20190710-00/?p=102678
I have reason to want to provide a different (inlinable) implementation if a type is complete.如果一个类型是完整的,我有理由想要提供一个不同的(可内联的)实现。
Is it an ORD violation for a templated function to behave differently in different translation units based on an if constexpr
in the function?模板化的 function 在基于 function 中的
if constexpr
的不同翻译单元中表现不同是否违反了 ORD? In a sense, it's the "same" function in the different translation units (it's not macros creating different definitions at a C++ source level, which is an ODR violation).从某种意义上说,它是不同翻译单元中的“相同”function(它不是在 C++ 源级别创建不同定义的宏,这是 ODR 违规)。
Here's a simple example:这是一个简单的例子:
#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 https://godbolt.org/z/q1soa58PY
For my application, I would want the two if constexpr
branches to outwardly act the same (unlike this example that prints different things) so from a correctness standpoint, it would be OK if the linker picked the assembly for either implementation and used that everywhere.对于我的应用程序,我希望这两个
if constexpr
分支在外观上表现相同(不像这个打印不同内容的示例),因此从正确性的角度来看,如果 linker 选择程序集用于任一实现并在任何地方使用它就可以了。 It's just that in a translation unit where T
is complete we may be able to get better performance (and I fully expect it to be inlined).只是在
T
完整的翻译单元中,我们可能可以获得更好的性能(我完全希望它是内联的)。
ODR is not based on "templated functions"; ODR 不是基于“模板函数”; it is based on actual functions.
它基于实际功能。 Templates generate functions based on template parameters.
模板根据模板参数生成函数。 Each unique set of template parameters represents a different function. Different functions generated from the same template are different functions .
每组唯一的模板参数代表一个不同的function。同一个模板生成的不同函数是不同的函数。 There are no ODR expectations between different functions, regardless of what created them.
不同功能之间没有 ODR 期望,无论创建它们的原因如何。
loggingGetRef<S>
is the name of a particular function. If you do something that causes loggingGetRef<S>
to generate differently due to constant expressions, you have ill-formed code (no diagnostic required). loggingGetRef<S>
是特定 function 的名称。如果您执行的操作导致loggingGetRef<S>
由于常量表达式而生成不同的内容,则您的代码格式错误(无需诊断)。 But that isn't a matter of ODR violations;但这不是 ODR 违规的问题; that's a violation of the rules of template instantiation.
这违反了模板实例化规则。 A template that is instantiated with a specific set of parameters must be the same in all translation units that instantiate it with those parameters.
使用一组特定参数实例化的模板在使用这些参数实例化它的所有翻译单元中必须相同。 Period.
时期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.