4
votes

I want to instantiate

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

that is, a function with a long signature. Now, I know how to do this:

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

But I have to duplicate the signature. Also, what if want specific instantiation for 5 different types - do I copy it 5 times? Doesn't make sense...

I was thinking maybe I could write

template decltype(foo<int>);

but for some reason this doesn't work. Why?

4
He is not trying to do any of those things. He is trying to explicitly instantiate this template.Puppy
You don't need the names of the function parameters, by the way: template foo<int>(int&, SomeType, AnotherType, EtcType, AsYouCanTell);. You can further shorten the type names by using type aliases.dyp
I wonder whether you can abuse C++14's variable templates to do this: Instead of explicitly instantiating the function template, maybe an explicit instantiation of a variable template referring to the function template might be sufficient. Possibly, a similar thing could be achieved with static data members and alias templates, but I'm not sure about that.dyp

4 Answers

7
votes

It actually works but the syntax is different:

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

decltype gives you a type but the explicit instantiation requires a declaration which is a type followed by a name.

Tried with GCC 4.9.1; it works as expected and compiles without any warnings even with the -pedantic flag.

4
votes

It's actually even simpler than @5gon12eder suggested:

template decltype(foo<int>) foo;

but yes, it's just like he said - decltype() only provides the type, and a signature is not really a type.

Edit: This doesn't work when the template has value arguments rather than just types, so if we have

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

then

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

will not compile, while

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

will.

1
votes

No, because of overloading

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

Now imagine, what is the minimum information required to explicitly instantiate the first one? Well, you need the full signature to disambiguate it, so

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

is the theoretical minimum amount of information. So what C++ requires actually has very little overhead:

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

If you don't want to type all that, then Konrad's suggestion of a macro is the way to go.

0
votes

I think this is a good, legitimate use for a macro:

#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