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?