The following code compiles without any error, though it seems to break ODR:
#include <iostream>
template<long Num>
class B;
template<long Num>
struct A {
template<long Num1>
friend void ffoo(A<Num1> a, B<Num>* = nullptr) {
std::cout << "@A ffoo(A<" << Num1 << ">, B<" << Num << ">*)" << std::endl;
}
};
template<long Num>
class B {
public:
friend void ffoo(A<Num> a, B<Num>* = nullptr) {
std::cout << "@B ffoo(A<" << Num << ">, B<" << Num << ">*)" << std::endl;
}
};
int main() {
ffoo(A<1>{}); // @A ffoo(A<1>, B<1>*)
B<1>* ptr = nullptr;
ffoo(A<1>{}, ptr); // @B ffoo(A<1>, B<1>*)
}
The ODR Rules allow cases for which breaking of ODR is IFNDR (ill formed no diagnostic required) all these cases seem to relate to programs with multiple translation units.
The first paragraph is quite clearly stating the requirement from a single translation unit:
[basic.def.odr]/1
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, template, default argument for a parameter (for a function in a given scope), or default template argument.
Does the above code break ODR? If it does, should breaking ODR inside a single translation unit require compiler diagnostics?
* Note: it seems that the friend template function in the code example do obey to the new rules of [temp.inst].
ffoo(A<1>, B<1>*)
isn't it? – Amir KirshB
is not a function template. Those are overloads – StoryTeller - Unslander Monicaffoo
coliru.stacked-crooked.com/a/954c266e2aae7645 – StoryTeller - Unslander Monica