Вызывает ли этот код нарушение правила одного определения? - PullRequest
0 голосов
/ 20 марта 2020

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

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?

Кажется очевидным, что будет нарушение ODR для g(), потому что в каждой единице перевода его реализация различна.

А как же f() и h()? Реализация (то есть поток токенов) каждого из них останется неизменной между единицами перевода. Но оба они неявно используют разные экземпляры C. Это имеет значение? Здесь нет поиска имени?

1 Ответ

1 голос
/ 20 марта 2020

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

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

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

...