Reputation: 1361
I'm trying to work out under what circumstances the following code might cause a violation of the one-definition rule.
header.h
#pragma once
#include <cstddef>
template<typename T, typename U>
class C {
friend std::size_t f() {
// Uses the template parameter that doesn't change
return sizeof(T);
}
friend std::size_t g() {
// Uses the template parameter that does change
return sizeof(U);
}
friend std::size_t h() {
// Does not refer to template parameters
return 0;
}
};
// Declarations to help name lookup
std::size_t f();
std::size_t g();
std::size_t h();
src1.cpp
#include "header.h"
// Cause definintion of f(), g() and h()
template class C<int, double>;
src2.cpp
#include "header.h"
// Cause definintion of f(), g() and h()
template class C<int, float>;
I've explicitly instantiated two different versions of the C
class template in the two different translation units. If I link the translation units together, do I have ODR violations?
It seems obvious that there would be an ODR violation for g()
because it has a different implementation in each translation unit.
But what about f()
and h()
?
The implementation (i.e. token stream) of each will remain unchanged between translation units. But they are both implicitly making use of different instantiations of C
. Does that make a difference? There is no name-lookup happening here is there?
Upvotes: 0
Views: 418
Reputation: 32742
A function that is defined as part of a friend declaration is implicitly an inline function, so there is no ODR violation as long as all of the definitions are the same in all translation units. It is not a member of the class that it is a friend of, but is a global function, similar to declaring the function as a friend, then defining the inline function once the definition of the class is complete.
This is the case for h
, which does not depend on any template parameter, and for f
, which does depend on a template parameter but that parameter has the same type (int
) in your example.
Function g
has different definitions in the src1.cpp and src2.cpp, so this is a potential ODR violation. This results in the program being ill-formed (no diagnostic required) if the function is ODR-used within both translation units.
Upvotes: 1