2013-08-11 3 views
10

Следующий кодЧастичная специализация для VARIADIC шаблона необходим первый не VARIADIC параметр шаблона

#include <iostream> 
#include <utility> 

template<typename F, typename... T> 
struct Wrapper{ }; 

template<typename T> 
struct is_wrapper : std::false_type {}; 

template<typename... T> 
struct is_wrapper<Wrapper<T...>> : std::true_type {}; 

//template<typename F, typename... T> 
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {}; 

int main() 
{ 
    Wrapper<int, double> w; 

    std::cout << is_wrapper<decltype(w)>::value << std::endl; 
} 

печатает 0. Однако, если один uncomments две строки в середине она печатает 1.

Почему Безразлично» t он всегда печатает 1? Должна ли вторая второстепенная специализация охватывать дело, которое, по-видимому, покрывается третьей (прокомментированной) частичной специализацией?

ответ

1

Код действительно должен соответствовать частичной специализации; Стандарт никогда фактически не запрещал это, но компиляторы действительно занимали некоторое время, чтобы реализовать вариативные шаблоны и их вычет должным образом. GCC соответствует с 4.9.0 и Clang по состоянию на 3.6. Соответствующий отчет об ошибке для Clang - #22191 (я не могу найти GCC, хотя).

0

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

Ваш код удивил меня, потому что я думаю, что вы правы, полная вариационная специализация вашей черты соответствует отверстиям ... Сначала я попытался использовать декларацию в прямом направлении вашего класса признаков и определить ТОЛЬКО полноразмерный специализация (Итак, если параметр признака не является экземпляром Wrapper, компиляция не выполняется). И то, что именно имеет ocurred, снова разочаровать меня:

#include <iostream> 
#include <utility> 

template<typename F , typename... T> 
struct Wrapper {}; 

template<typename T> 
struct is_wrapper; 

//template<typename T> 
//struct is_wrapper : std::false_type {}; 

template<typename... T> 
struct is_wrapper<Wrapper<T...>> : std::true_type {}; 

//template<typename F, typename... T> 
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {}; 

using my_wrapper_type = Wrapper<int,double>; 

int main() 
{ 
    std::cout << std::boolalpha << is_wrapper<my_wrapper_type>::value << std::endl; 
}//"Invalid use of incomplete type" ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Наконец я попытался с помощью метода прямой декларации в Wrapper классе. И удивительно, что это работает:

#include <iostream> 
#include <utility> 

template<typename... T> 
struct Wrapper; 

template<typename F, typename... T> 
struct Wrapper<F,T...>{ }; 


template<typename T> 
struct is_wrapper : std::false_type {}; 

template<typename... T> 
struct is_wrapper<Wrapper<T...>> : std::true_type {}; 

//template<typename F, typename... T> 
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {}; 


using my_wrapper_type = Wrapper<int,double>; 

int main() 
{ 
    std::cout << std::boolalpha << is_wrapper<my_wrapper_type>::value << std::endl; 
} 

Печатается:

истинные

Here это код работает на ideone.

С уважением, я не понимаю, почему ваш код не работает, а мои работы. Его ошибка компилятора, или есть что-то, чего нам не хватает? Не знаю.

+0

Разница - это количество параметров шаблона для шаблона класса 'Wrapper'. Ваша (вторая) версия имеет только один параметр шаблона, тогда как версия OP имеет два параметра. Ваша частичная специализация 'struct Wrapper ' не меняет этого. – dyp

+0

@DyP ОК, но если у вас есть шаблон с двумя параметрами (один параметр обычного шаблона и параметр вариационного шаблона), и вы передаете этот шаблон в виде вариационного пакета, то вариационный пакет не должен расширять соответствие первому нормальному параметру, и второй параметр (параметр вариации)?Это то, чего я не понимаю, почему пакет не расширяется таким образом. – Manu343726

+0

Я все еще пытаюсь выяснить, где (и почему) Стандарт запрещает частичную специализацию для соответствия пакету параметров в этом случае. Угадайте, что это где-то рядом [temp.deduct.type]/9. (Расширение пакета отличается от вывода.) – dyp

0

Если я понимаю, а ваши проблемы, это просто приоритет специализации,

is_wrapper<decltype(w)> 

Может быть специализированы на 2 шаблона:

template<typename T> // exact specialization 
template<typename... T> // variadic specialization with one parameter 

В этом случае компилятор выбрать приоритет точную специализацию и поэтому шаблон никогда не бывает в вашем случае.

+0

Это неверно. Частичные специализации всегда предпочтительнее первичных шаблонов (и должны быть более специализированными, так или иначе), см. §14.5.5.1. – Columbo

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