шаблонни псевдоними и sfinae

В случай на грешка при заместване, включваща псевдоним на шаблон (напр. псевдоним на шаблон на липсващо име на член, както в кодовия фрагмент по-долу), трябва ли да се задейства грешка?

Clang и gcc изглежда не са съгласни по това:

// some types
struct bar { };

struct foo {
    typedef void member_type;
};


// template alias
template<class T>
using member = typename T::member_type;


template<class T>
void baz(... ) { }

// only works for gcc, clang fails with: no type named 'member_type'
// in 'bar'
template<class T>
void baz( member<T>* ) { }


int main(int, char** ) {

    baz<bar>(0);            // picks first
    baz<foo>(0);            // picks second

    return 0;
}

Така че въпросът е: кой е прав и защо?

Благодаря :-)


person max    schedule 05.12.2012    source източник
comment
Какво казва clang -v? Clang 3.3 trunk компилира кода съвсем добре.   -  person Xeo    schedule 05.12.2012
comment
Debian clang версия 3.1-8 тук, изглежда просто трябва да изчакам. Благодаря за обратната връзка!   -  person max    schedule 05.12.2012
comment
Можете ли да се отървете от псевдонима на шаблона, просто за да опростите малко нещата   -  person David    schedule 05.12.2012
comment
@Dave: Целият смисъл на въпроса беше относно използването на псевдоними, така че...   -  person Xeo    schedule 05.12.2012
comment
@Xeo о, съжалявам. Погледнах само кода и си помислих, че е само за SFINAE.   -  person David    schedule 06.12.2012


Отговори (1)


Съгласно стандартите, очевидно GCC е правилният, тъй като шаблонът за псевдоним трябва незабавно да бъде заменен и тогава нормален/обичаен SFINAE се прилага към typename T::member_type по-късно, когато T е известен.

Но в момента има проблем за това, вижте http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1554.

Според резултата от срещите изглежда, че поведението на clangs е желано: Замяната на T ще бъде извършена в контекста на шаблона за псевдоним (въпреки че по време на замяната в typename T::member_type вече няма препратка към шаблона за псевдоним - той все пак ще трябва да бъде посочен като източник откъде произлиза моделът на типа параметър, ако това е начинът, по който е реализиран).


Това е подобно на друга ситуация, при която моделите се изхвърлят във времето за дефиниране, което може да повлияе на семантиката на инстанцирането

template<int I>
void f(int x[I]);

int main() {
  f<0>(nullptr);
}

И в този случай според мен стандартът е нормативно ясен, че параметърът незабавно се заменя с int* и по този начин инстанцията работи. Вижте http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1322 .

person Johannes Schaub - litb    schedule 05.12.2012
comment
Според резултата от срещите изглежда, че поведението на clangs е желано -- няма ли това напълно да убие всеки псевдоним EnableIf там? Изглежда е крайно нежелателно шаблоните за псевдоними да не генерират SFINAE меки грешки. - person Xeo; 05.12.2012
comment
@Xeo да, това би било лошо. И всъщност clang trunk приема псевдонима EnableIf, така че ми се струва, че поведението, което питащият наблюдава, е просто clang бъг и че резюмето на проблема в сайта wg21 е просто объркващо (IMHO). - person Johannes Schaub - litb; 05.12.2012
comment
Да, бях объркан, тъй като вече коментирах, че стволът компилира кода добре. - person Xeo; 05.12.2012