sfinae с decltype: ошибка в clang или gcc?

Clang-3.2 может компилировать и код вести себя как положено:

struct have_f { int f(int i) {return 10;} };

struct empty {};

template <class T>
struct outer {
T t;

// if T have f(), define  outer_f()
template<class U=decltype(t.f(1))>
int outer_f(int i) { return t.f(i); }
};

int main() {
outer<have_f>  o1;
outer<empty>   o2;

// to silence unused var warning
return  o1.outer_f(10) + sizeof(o2);
}

GCC любой версии отклоняется с:

t.cc:13:6: error: ‘struct empty’ has no member named ‘f’
int outer_f(int i) { return t.f(i); }
^

Кто прав? Gcc или Clang?

Обратите внимание, что там было аналогичный вопрос, без реального ответа.

10

Решение

Я считаю, что проблема 14.6.3 [temp.nondep]:

1 — Независимые имена, используемые в определении шаблона, находятся с использованием обычного поиска имен и привязываются в той точке, в которой они используются.

В приведенном примере описывается, что неправильно сформированное выражение в определении шаблона «может быть диагностирован либо [в определении шаблона], либо в момент создания».

По умолчанию Шаблон-аргумент (14.1p9) U=decltype(t.f(1)) является независимым именем в контексте реализации struct outer (то есть, он не зависит от аргумента шаблона к своему собственному шаблону), поэтому он плохо сформирован для реализации struct outer с T = struct empty, Стандарт не содержит явного описания того, где оцениваются аргументы шаблона по умолчанию, но единственный разумный вывод заключается в том, что они обрабатываются как любая другая конструкция и оцениваются в точке, в которой они встречаются (или, в этом примере, в точке создания экземпляра struct outer шаблон). Я не вижу никакой возможности для компилятора задерживать оценку независимых аргументов шаблона по умолчанию для контекстов, в которых применяется SFINAE.

К счастью, решение простое: просто создайте шаблон по умолчанию U зависимое имя:

    // if T have f(), define  outer_f()
template<class T2 = T, class U=decltype(static_cast<T2 &>(t).f(1))>
int outer_f(int i) { return t.f(i); }
9

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

Других решений пока нет …

По вопросам рекламы [email protected]