2015-08-04 1 views
1

В C++, я хотел бы быть в состоянии сказать:Могу ли я сделать один шаблон <typename T> применительно к нескольким определениям/объявлениям?

template <typename T> { 
void foo(T t1); 
void bar(T t1, T t2); 
} 

т.е. имеют template <typename T> применяться к нескольким определениям/деклараций. Синтаксис { } в приведенном выше не компилируется; есть ли другой способ выразить то же самое?

Примечание: Завершение функций в struct/class не будет выполнено, я хочу что-то, что является как кратким, так и без каких-либо фиктивных объектов.

+3

Нет, нет такого единорога. –

+0

Если вы можете подождать, вы можете использовать типы параметров 'auto' из концепций C++ 17. – CoffeeandCode

+0

@CoffeeandCode: Ну, увидев, как я живу без этого сейчас, я думаю, я могу подождать :-), но как изменится C + + 17 'auto'? Если вы сделаете это в ответ, я смогу его продвинуть ... – einpoklum

ответ

4

Если вы можете подождать C++17 concepts, вы можете использовать типы параметров auto вместо использования шаблонов.

Скажем, у меня есть следующий C++ 17 функции:

auto func(auto x, auto y){ 
    return x + y; 
} 

Это может быть переписан в C++ 14, как это:

template<typename T, typename U> 
auto func(T x, U y){ 
    return x + y; 
} 

Какой может быть переписана еще раз в C++ 11 следующим образом:

template<typename T, typename U> 
auto func(T x, U y) -> typename std::decay<decltype(x + y)>::type{ 
    return x + y; 
} 

как @TC изложенные в комментариях, здесь нужен std::decay, потому что семантика типа автоматического возврата в C++ 14 будет затухать заключительный оператор, тогда как decltype(x + y) не будет разлагать тип выражений. Если мы хотим, чтобы не распадаться возвращения выражения типа, который мы бы написать:

// template here for c++14 
decltype(auto) func(auto x, auto y){ 
    return x + y; 
} 

Таким образом, учитывая эту информацию мы могли бы переписать свои функции, как это:

void foo(auto t1); 
void bar(auto t1, auto t2); 

Вспоминая, что если мы когда-нибудь нужно укажите типы аргументов, которые нам понадобятся для использования decltype.


Если вы собираетесь на использование типов обширно шаблоны гораздо лучше идея, но сохранить краткость объявления функции в определении функции мы могли бы написать некоторые using заявления для типов:

void bar(auto t1, auto t2){ 
    using type_t1 = std::decay_t<decltype(t1)>; 
    using type_t2 = std::decay_t<decltype(t2)>; 
} 

Необходимость std::decay_t в этой ситуации возникает, если мы передаем указатель или ссылку с некоторым квалификатором cv. Нам нужен только базовый тип.

Тогда для обеспечения, что основные типы type_t1 и type_t2 такие же, как в вашем примере мы могли бы использовать SFINAE, чтобы исключить создание экземпляра bar, где они не являются:

auto bar(auto t1, auto t2) -> std::enable_if_t<std::is_same<std::decay_t<decltype(t1)>, std::decay_t<decltype(t2)>>::value>{ 
    using type = std::decay_t<decltype(t1)>; 
} 

снова, разлагающихся тип так что если мы получим указатели, мы сравниваем базовый тип.

Не забудьте спросить себя, если это все стоит, просто не нужно писать template<typename T> еще несколько раз.

+0

Причина для downvote? – CoffeeandCode

+0

(Не downvoter) Ваши версии C++ 14 и C++ 11 не совпадают. Кроме того, эта финальная сфина довольно смехотворна. –

+0

@ T.C. как так? Я исправлю это, если вы сообщите мне, как – CoffeeandCode

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