баг или фича?
От: saf_e  
Дата: 16.06.15 09:47
Оценка: -1
struct a
{
    static std::string name() {return "a";}
};

struct b
{
    static std::string name() {return "b";}
};

struct c
{
    static std::string name() {return "c";}
};

template<typename _T>
std::string get_name()
{
    return _T::name();
}

template<typename _T, typename... _tail>
std::string get_name()
{
    return _T::name() + " " + get_name<_tail ...>();
}

int main()
{
    std::cout << get_name<a, b, c, a>();
}


Вот такое не компилируется (VS2013 udp 4). Как полечить?
Re: баг или фича?
От: alxn1 Россия  
Дата: 16.06.15 10:00
Оценка: 4 (1)
Это фича. Лечить можно так:

template< typename _T, typename... _tail >
struct get_name_
{
    static std::string get() { return _T::name() + " " + get_name_< _tail... >::get(); }
};

template< typename _T >
struct get_name_< _T >
{
    static std::string get() { return _T::name(); }
};

template<typename... _tail>
std::string get_name()
{
    return get_name_<_tail ...>::get();
}
Отредактировано 16.06.2015 10:01 alxn1 . Предыдущая версия .
Re[2]: баг или фича?
От: saf_e  
Дата: 16.06.15 10:04
Оценка:
Здравствуйте, alxn1, Вы писали:

A>Это фича. Лечить можно так:


A>
A>template< typename _T, typename... _tail >
A>struct get_name_
A>{
A>    static std::string get() { return _T::name() + " " + get_name_< _tail... >::get(); }
A>};

A>template< typename _T >
A>struct get_name_< _T >
A>{
A>    static std::string get() { return _T::name(); }
A>};

A>template<typename... _tail>
A>std::string get_name()
A>{
A>    return get_name_<_tail ...>::get();
A>}
A>


Спасибо работает, теперь вопрос почему (в идеале со ссылкой на стандарт)?
Re[3]: баг или фича?
От: VTT http://vtt.to
Дата: 16.06.15 11:39
Оценка: 26 (3)
Здравствуйте, saf_e, Вы писали:

_>Спасибо работает, теперь вопрос почему (в идеале со ссылкой на стандарт)?


Ваш исходный код не работает из-за того, что на когда на последнем шаге инстанцируется
get_name<a>()

список параметров шаблона функции
template<typename _T, typename... _tail>
std::string get_name()

оказывается пуст и его специализация оказывается аналогичной специализации шаблона функции
template<typename _T>
std::string get_name()

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

14.5.6.2 Partial ordering of function templates
1
If a function template is overloaded, the use of a function template specialization might be ambiguous
because template argument deduction (14.8.2) may associate the function template specialization with more
than one function template declaration.


А в случае с использованием шаблона класса
template< typename _T, typename... _tail >
struct get_name_

и его специализации (заметьте, что у вас было два шаблона функции, а тут только один шаблон класса и его специализация)
template< typename _T >
struct get_name_< _T >

такой проблемы не возникает, так как компилятор выбирает на последнем шаге "более специализированный" вариант:

14.5.5.1 Matching of class template partial specializations
1
When a class template is used in a context that requires an instantiation of the class, it is necessary to
determine whether the instantiation is to be generated using the primary template or one of the partial
specializations. This is done by matching the template arguments of the class template specialization with
the template argument lists of the partial specializations.

(1.1)
If exactly one matching specialization is found, the instantiation is generated from that specialization.

(1.2)
If more than one matching specialization is found, the partial order rules (14.5.5.2) are used to deter-
mine whether one of the specializations is more specialized than the others.

Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[4]: баг или фича?
От: saf_e  
Дата: 16.06.15 12:07
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>Здравствуйте, saf_e, Вы писали:


_>>Спасибо работает, теперь вопрос почему (в идеале со ссылкой на стандарт)?


VTT>Ваш исходный код не работает из-за того, что на когда на последнем шаге инстанцируется


Спасибо, вопрос закрыт.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.