简体   繁体   English

完全专业化的模板 function 是否违反了常规 function 的 ODR?

[英]Does fully specialized template function violate ODR with a regular function?

I just realized this snippet compiles safely without any warnings on g++ and clang .我刚刚意识到这个片段可以安全地编译,而g++clang上没有任何警告。 (given --std=c++14 --Wall ) (给定--std=c++14 --Wall

#include <iostream>

template <typename T>
void foo(const T& a, const T& b)
{
    std::cout << "1. Template version called.\n";
}

template <>
void foo(const int& a, const int& b)
{
    std::cout << "2. Template specialized version called.\n";
}

void foo(const int& a, const int& b)
{
    std::cout << "3. Regular function version called.\n";
}

int main()
{
    // Prints: 3. Regular function version called.
    foo(4, 2);
}

But I am not sure if, according to the standards, the 2. Template specialized version and 3. Regular function version violates ODR or not.但根据标准,我不确定2. Template specialized version3. Regular function version违反 ODR。

So, does this violate ODR?那么,这是否违反了 ODR?

If not, is it guaranteed that foo(4,2) always calls the 3. Regular function version ?如果不是,是否保证foo(4,2)总是调用3. Regular function version
Or is it compiler dependent?还是它依赖于编译器?

Short answer: No it does not violate ODR and yes it is guaranteed to call the regular function, as long as you use an C++ standard compliant compiler.简短回答:不,它不违反 ODR,是的,只要您使用符合 C++ 标准的编译器,就可以保证调用常规的 function。

When calling foo , the compiler first makes a list of candidate functions, by looking up the name foo .调用foo时,编译器首先通过查找名称foo来生成候选函数列表。 On of the candidates is the regular function.候选中的一个是常规的 function。 It also goes through template type deduction and eventually finds your specialization to be a second candidate for overload resolution.它还通过模板类型推导,最终发现您的专业化是重载解决方案的第二个候选者。

After that the compiler produces a set of viable candidates by matching the number of arguments and testing if there is an implicit conversion between the arguments and the parameters you provided.之后,编译器通过匹配 arguments 的数量并测试 arguments 和您提供的参数之间是否存在隐式转换来生成一组可行的候选者。 Both the candidates (the regular function and the specialized template) pass this stage and are viable.两个候选(常规 function 和专用模板)都通过了这个阶段并且是可行的。

Then, the compiler decides which of the viable candidates is the best, by following a set of rules which are described eg here .然后,编译器通过遵循例如这里描述的一组规则来决定哪个可行的候选者是最好的。 Normally it would take the candidate whose parameter types match the argument types best (rule 1.-3. as in the linked page).通常,它会采用参数类型与参数类型最匹配的候选者(规则 1.-3。如链接页面中所示)。 However because your parameter types are exactly the same, it goes to rule 4, which says that non-templated functions take precedence over template-specalizations.但是,由于您的参数类型完全相同,因此进入规则 4,即非模板化函数优先于模板规范化。 So the regular functions is picked!所以选择了常规功能!

One additional note on function template specialization.关于 function 模板专业化的附加说明。 There are reasons to prefer overloading functions to specialized function templates.有理由更喜欢重载函数而不是专门的 function 模板。 If providing a specialization where two or more templates could be the "parent", you can run into strange effects, where declaration order affects the actual outcome.如果提供两个或多个模板可以作为“父”的特化,您可能会遇到奇怪的效果,其中声明顺序会影响实际结果。 You can find a more information on this topic and an example in the answer to this question .您可以在此问题的答案中找到有关此主题的更多信息和示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM