Я пытаюсь выяснить, при каких обстоятельствах следующий код может привести к нарушению правила одного определения.
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>;
Я явно создал две разные версии шаблона класса C
в двух разных единицах перевода. Если я свяжу единицы перевода вместе, будут ли у меня нарушения ODR?
Кажется очевидным, что для g()
будет нарушение ODR, потому что оно имеет разную реализацию в каждой единице перевода.
А как же f()
и h()
? Реализация (то есть поток токенов) каждого из них останется неизменной между единицами перевода. Но они оба неявно используют разные экземпляры C
. Это имеет значение? Здесь не происходит поиска имени, не так ли?