Вызывает ли этот код нарушение правила одного определения?

Я пытаюсь выяснить, при каких обстоятельствах следующий код может привести к нарушению правила одного определения.

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. Это имеет значение? Здесь не происходит поиска имени, не так ли?


person Alastair Harrison    schedule 20.03.2020    source источник


Ответы (1)


Функция, определенная как часть объявления друга, неявно является встроенной функцией, поэтому нарушения ODR нет, если все определения одинаковы во всех единицах перевода. Это не член класса, которому он является другом, а глобальная функция, аналогичная объявлению функции как друга, а затем определению встроенной функции после завершения определения класса.

Это относится к h, который не зависит ни от одного параметра шаблона, и к f, который зависит от параметра шаблона, но этот параметр имеет тот же тип (int) в вашем примере.

Функция g имеет разные определения в src1.cpp и src2.cpp, так что это потенциальное нарушение ODR. Это приводит к неправильному формату программы (диагностика не требуется), если функция используется ODR в обеих единицах перевода.

person 1201ProgramAlarm    schedule 20.03.2020