Могут ли различные шаблоны псевдонимов разрешить возможные нарушения ODR в разных библиотеках? - PullRequest
0 голосов
/ 13 февраля 2019

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

// foo.h
#ifdef USE_DOUBLE
template <typename T>
struct foo { T* value; double x; };
#else
template <typename T>
struct foo { T* value; };
#endif

struct c;

// a_lib.cpp
#include "foo.h"
struct a { foo<a> m_a; };
struct a_helper { foo<c> m_c; };

// b_lib.cpp
#define USE_DOUBLE
struct b { foo<b> b; };
struct b_helper { foo<c> m_c; };
  1. Я предполагаю, что foo<a> и foo<b> не имеют нарушения ODR, верно?
  2. Но что разные определенияиз foo<c>, привнесенных a_helper и b_helper, просто невероятно схематично, верно?

Подвох в том, что у меня есть это в огромном проекте.Кроме того, вероятно (но не уверен), что у меня есть только эквивалент не перекрывающихся a и b, а не проблемных a_helper и b_helper.Однако я не совсем уверен.

Мне интересно, смогу ли я избежать этой проблемы, изменив foo на шаблон псевдонима:

template <typename T>
struct foo_double_impl { T* value; double x; };

template <typename T>
struct foo_impl { T* value; };

#ifdef USE_DOUBLE
template <typename T>
using foo = foo_double_impl<T>;
#else
template <typename T>
using foo = foo_impl<T>;
#endif
Теперь вместо двух разных определений foo у нас теперь есть определения foo_impl и foo_double_impl.Разрешает ли это нарушение ODR?Или нарушение ODR сохраняется, потому что есть два разных шаблона псевдонима foo?

1 Ответ

0 голосов
/ 13 февраля 2019

ODR указывается довольно долго в стандарте , который сводится к тому, что вы должны

  • иметь только одно определение не встроенной функции или переменной
  • Имейте хотя бы одно определение из всего, что используется.Множество определений должны быть точно одинаковыми, включая
    • иметь одинаковую последовательность токенов
    • иметь последовательность токенов, означающую одно и то же
    • Пусть все поиски соответствующих токенов найдут одно и то же

Подводя итог, они действительно действительно должны быть идентичны во всех возможных манерах.

Во всех ваших сценариях foo нарушает ODR, имея различную последовательность токенов.


Лучшим исправлением без изменения библиотек являются встроенные пространства имен

#ifdef USE_DOUBLE
inline
#endif
namespace D {
    template <typename T>
    struct foo { T* value; double x; };
} 

#ifndef USE_DOUBLE
inline
#endif
namespace ND {
    template <typename T>
    struct foo { T* value; };
}
...