由于 if constexpr 而使内联模板化函数具有不同的行为是否违反 ODR?

Is it an ODR violation to have an inline templated function have different behavior due to if constexpr?

可以检测类型是否完整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> 由于常量表达式而产生不同的结果,你就有了 ill-formed 代码(不需要诊断)。但这不是 ODR 违规的问题;这违反了模板实例化规则。使用一组特定参数实例化的模板在使用这些参数实例化它的所有翻译单元中必须相同。期间.