2015-02-05 2 views
3

Я хочу, чтобы создать экземплярМогу ли я использовать decltype (или что-то подобное) для явного создания экземпляра шаблона без дублирования подписи?

template<typename T> void foo(
    T& t, 
    SomeType some_parameter, 
    AnotherType another_parameter, 
    EtcType yet_another_parameter, 
    AsYouCanTell this_is_a_very_long_signature); 

то есть, функция с длинной подписью. Теперь я знаю, как это сделать:

template void foo<int>(
    int& t, 
    SomeType some_parameter, 
    AnotherType another_parameter, 
    EtcType yet_another_parameter, 
    AsYouCanTell this_is_a_very_long_signature); 

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

Я думал, может быть, я мог бы написать

template decltype(foo<int>); 

, но по какой-то причине это не работает. Зачем?

+1

Он не пытается ничего делать. Он пытается явно создать экземпляр этого шаблона. – Puppy

+1

Вам не нужны имена параметров функции, кстати: 'template foo (int &, SomeType, AnotherType, EtcType, AsYouCanTell);'. Вы также можете сократить имена типов с помощью псевдонимов типов. – dyp

+0

Интересно, можете ли вы использовать шаблоны переменных C++ 14 для этого: вместо явного создания экземпляра шаблона функции может быть достаточно явного создания шаблона переменной, ссылающегося на шаблон функции. Возможно, аналогичная вещь может быть достигнута с помощью статических элементов данных и шаблонов псевдонимов, но я не уверен в этом. – dyp

ответ

6

Это на самом деле работает, но синтаксис отличается:

template 
decltype(foo<int>) foo<int>; 

decltype дает вам тип но явная конкретизация требует декларации который является типом с последующим именем.

Пробовал с GCC 4.9.1; он работает так, как ожидалось, и компилируется без каких-либо предупреждений даже с флагом -pedantic.

+0

@ dyp Я не юрист языка. Я признаю, что я нашел это решение в основном случайно и был счастлив, что GCC принял его. Мне было бы интересно услышать, что стандарты должны сказать об этом. – 5gon12eder

+0

И этот ответ обеспечивает ожидаемую ошибку компилятора, если вы не предоставили реализацию: (clang 3.5.0) 'error: явное создание шаблона неопределенной функции foo''. Я попробовал другое решение, но он дает мне только ошибки компоновщика, когда реализация отсутствует. –

+1

Я неохотно говорю, что это полностью законно из-за [dcl.fct]/12 * «Тип объявления типа может использоваться для объявления функции, но не используется для определения функции». * Но я думаю, что хотя утверждение в ответе является * явным определением ин формации *, я не думаю, что это считается определением функции wrt [dcl.fct]/12. – dyp

0

Я думаю, что это хорошо, законное использование для макроса:

#define INSTANTIATE_FOO(type) \ 
    template void foo<type>(type& t, \ 
        SomeType some_parameter, \ 
        AnotherType another_parameter, \ 
        EtcType yet_another_parameter, \ 
        AsYouCanTell this_is_a_very_long_signature); 

INSTANTIATE_FOO(int) 
INSTANTIATE_FOO(float) 
INSTANTIATE_FOO(my_little_dragon) 

#undef INSTANTIATE_FOO 
+0

Вы по-прежнему дублируете подпись хотя бы один раз - при определении макроса. И если вы попытаетесь избежать дублирования, он станет запутанным макросом ... – einpoklum

1

Нет, из-за перегрузки

template<typename T> void foo(T& t, 
        SomeType some_parameter, 
        AnotherType another_parameter, 
        EtcType yet_another_parameter, 
        AsYouCanTell this_is_a_very_long_signature); 
template<template T> void foo(T& t); //completely unrelated function 
template<template T> void foo(char); //another completely unrelated function 

А теперь представьте себе, какова минимальная информация, необходимая для явного экземпляра первого один? Ну, вам нужна полная подпись, чтобы устранить ее, поэтому

explicit int foo(int&, SomeType, AnotherType, EtcType, AsYouCanTell) 

- теоретический минимальный объем информации. Так что C++ требует на самом деле имеет очень небольшие накладные расходы:

template void foo<int>(int& t, SomeType, AnotherType, EtcType, AsYouCanTell); 

Если вы не хотите вводить все это, то предложение Конрада макроса является путь.

+0

Но у меня нет ни одной из этих перегруженных функций. – einpoklum

+0

Язык должен использовать формат для явного экземпляра, который будет действительным _no matter_, какие существуют другие функции. Независимо от того, действительно ли они существуют, это не имеет значения. Они должны существовать, и синтаксис должен поддерживать это. –

3

Это на самом деле даже проще, чем @ 5gon12eder предложил:

template decltype(foo<int>) foo; 

но да, это так же, как он сказал, - decltype() обеспечивает только тип, и подпись не очень типа.

Edit: Это не работает, когда шаблон имеет аргументы значение, а не только типы, так что если у нас есть

template <typename T, unsigned Val> bar(T t); 

затем

template decltype(bar<int, 1>) bar; 

не компилировать, а

template decltype(bar<int, 1>) bar<int, 1>; 

будет.

+1

Я удивлен, что это работает. Означает ли это, что типы выводятся для второго 'foo'? Это круто. – 5gon12eder

+0

@dyp Но он должен быть скомпилирован как искаженное имя для правильного экземпляра шаблона или компоновщик не может найти определение. Я просмотрел код сборки, и он читает то же самое, независимо от того, предоставляется ли «». – 5gon12eder

+0

@dyp Шаблонные аргументы, очевидно, должны быть выведены из этого типа. – Columbo

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

  • Нет связанных вопросов^_^