2013-09-17 4 views
14

Я нашел этот кусок кода поддельного (надуманный пример ниже):шаблона специализация с преобразованием типа

template <int I, typename T> 
struct foo 
{ 
    static int bar() 
    { 
     return 1; 
    } 
}; 

template <std::size_t Index, typename T> 
struct foo<Index, T*> 
{ 
    static int bar() 
    { 
     return 2; 
    } 
}; 

Пожалуйста, обратите внимание, что специализация использует другой тип (по ошибке). Удивительно, что он компилируется без каких-либо ошибок (или предупреждений) как с GCC 4.8.1, так и с Clang 3.4. Но что еще более странно для линии GCC foo<0, int*>::bar() приводит к 1, но Clang дает 2. Что происходит? До сих пор ли он считается специализацией по стандарту?

+1

Специализация size_t должна быть ошибкой (int! = Size_t) –

+0

Итак, оба компилятора ошибочны? Звучит вполне ... невероятно ;-) – magor

+0

Почему вы, ребята, думаете, что это специализация? – us2012

ответ

2

Gcc неправ, потому что вы просто не можете назвать эту специализацию. Просто удалите первичное определение шаблона:

template <int I, typename T> 
struct foo; 

template <std::size_t Index> 
struct foo<Index, int*> { 
    static int bar() { 
    return 2; 
    } 
}; 

int main() { 
    std::cout << foo<std::size_t(0), int*>::bar() << std::endl; // nope, not work 
    std::cout << foo<0, int*>::bar() << std::endl; // nope, not work 
} 

Посмотреть живой example. И код this должен сообщать о двусмысленной частичной специализации, но это не (для gcc). Clang report "неоднозначный".

PS I argee, эта часть не достаточно покрыта стандартом.

обновление

лязг в этой ситуации не будет работать с перечислений, example.

+0

Я почти уверен, что это ошибка GCC, позже я напишу отчет об ошибке. Между тем, я думаю, я должен принять ваш ответ :-) И я буду держать вас в курсе – magor

0

Ограничения на частично специализирующийся шаблон класса на аргумент шаблона не типа 14.5.5 [temp.class.spec] пункт 8 списка следующее ограничение:

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

Выражение аргумента с использованием size_t включает в себя преобразование в int (size_t это беззнаковое) и, таким образом, не является простым идентификатором.

+0

@ruslo: он уверен, что это простой идентификатор, но на самом деле это 'int (Index)', который больше не является простым идентификатором. –

+0

@ruslo: это может быть верно для идентификатора, но ограничение явно говорит об этом выражении и должно стать «int (Index)», поскольку тип объекта, идентифицированного идентификатором, является «std :: size_t», который гарантированно не быть 'int'. –

Смежные вопросы