Лучшее совпадение не найдено ADL после момента создания. Это UB?

Рассмотрим следующий код, в котором расположение перегрузок f вызывает некоторое неинтуитивное поведение. Код компилируется без предупреждений как в Clang 3.4.1, так и в gcc 4.8.

template<typename T>
struct A
{
static const int value = sizeof(f(T()));
};

struct B
{
};

struct D : B
{
};

char f(B);

// instantiates A<D>, unqualified name lookup finds f(B) via ADL
static_assert(A<D>::value == sizeof(f(B())), ""); // passes

long f(D); // but wait, f(D) would be a better match!

// A<D> is already instantiated, f(D) is not found
static_assert(A<D>::value == sizeof(f(B())), ""); // passes

Стандарт C ++ 11 предполагает, что приведенный выше код вызывает неопределенное поведение:

[Temp.dep.candidate]

Для вызова функции, который зависит от параметра шаблона, функции-кандидаты находятся с использованием обычного
правила поиска кроме этого:

  • Только для части поиска, использующей поиск по неполному имени или поиск по квалифицированному имени
    Найдены объявления функций из контекста определения шаблона.
  • Для части поиска, использующей связанные пространства имен, только объявления функций, найденные в
    либо контекст определения шаблона, либо контекст создания шаблона найдены.

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

Вызывает ли приведенный выше код это конкретное неопределенное поведение? Можно ли ожидать, что качественная реализация сообщит о предупреждении?

3

Решение

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

Да. [Temp.point] / 7:

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

Точка инстанции находится сразу после первого static_assert-declaration:

Для […] специализации для […] статического члена данных класса
шаблон, если специализация неявно создается, потому что
на него ссылаются из другой специализации шаблона […].
В противном случае точка создания такой специализации сразу же следует за объявлением или определением области пространства имен, которое
относится к специализации.

Таким образом, было бы действительно лучшее совпадение, если бы мы рассмотрели второе объявление функции — что мы не смогли, так как оно объявлено после момента создания экземпляра A<D>::value, Согласно правилу, которое вы цитировали, код вызывает неопределенное поведение.
Правило в основном расширяет ODR для поиска зависимых имен в шаблонах.

Можно ли ожидать, что качественная реализация сообщит о предупреждении?

Я бы не стал. Учтите также, что неопределенное поведение возвращается ко времени компиляции; Компилятору разрешено, но не обязательно выдавать предупреждение или сообщение об ошибке, если код вызывает UB. Не ожидайте, что компиляторы всегда будут указывать на недопустимый код.

2

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector