0

What's the correct syntax for naming a specific instance of a template static method?

All the following attempts seem to be wrong:

struct S
{
    template<int x> static int f() { return x; }
    using g1 = f<1>;
    template using g2 = f<1>;
    template<> using g3 = f<1>;
};
Danra
  • 9,546
  • 5
  • 59
  • 117
  • 3
    `using` names a type. A function is not a type. `f<1>` is a function. Can you explain what you want this naming to do, and how you want to use it? Suppose you had `static int f_1() { return 1; }`, explain what you'd want to do with it instead of `f<1>` and how you'd do it. – Yakk - Adam Nevraumont Jan 16 '17 at 16:47
  • @Yakk I'm interested not in naming a type, but in naming f<1> by some name (say g), so that later I can call g() instead of f<1>, with the intent being DRY in case there are many calls to this specific instantiation of the function template. It's possible (reasonable, following what you write) that using is not the tool for this; how should I do it? – Danra Jan 16 '17 at 16:53
  • 1
    if you want a *variable* that can hold the *value* `f<1>`, just use auto: `auto g = f<1>` – Caleth Jan 16 '17 at 17:15
  • @Caleth Yup, that works. Though has to be outside of the struct definition. http://melpon.org/wandbox/permlink/LZ15s9WTlPEEKexL You are welcome to post it as an answer. – Danra Jan 16 '17 at 17:23
  • @Caleth Though, it would be nice to be able to just *name* the specific instantiation without actually assigning it to a variable. – Danra Jan 16 '17 at 17:26
  • It has a name, f<1> – Caleth Jan 16 '17 at 17:26
  • @Caleth Right, but as I wrote above, naming it by some name which doesn't require giving the template parameter each time is DRYer. So if there are many uses of f<1>, and then you decided you actually need f<2>, you can change it in just one place - where the name is defined - instead of all the places where this instantiation is used. – Danra Jan 16 '17 at 17:28

4 Answers4

0

C++ doesn't like local structs that have template methods (see here)

you need to lift it out. Also are you wanting to use decltype for you typedefs? e.g.

typedef decltype(f<0>) t;
using g1 = decltype(f<0>);

those will only give you types. Probably best to call them directly e.g. S::f<0> etc

Community
  • 1
  • 1
Biggy Smith
  • 910
  • 7
  • 14
0
struct S {
  template<int x> static int f() { return x; }
  static int g1() { return f<1>(); }
};

note that here g1 is not f<1> -- &S::f<1> != &S::g1 for example. But calling it has the same effect. (With some linkers this may not be true; msvc linker, or gold linker set aggressively)

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

using defines an alias, it does not specialize anything. using defines aliases for classes, types, etc... Aliases, and specializations, are two completely different things.

f() is not a class. It's a method. Classes, various types, and things of this nature, can be aliased with using or typedef. But not functions or methods.

If you want to specialize the class method, define the specialization for the method outside the class:

template<>
int S::f<1>()
{
    return 0; // Or whatever your specialization function needs to do.
}

If you want an alias for a function, this is basically a wrapper:

int f1()
{
    return f<1>();
}

So, calling f1() now calls the specialized method.

If you want to both specialize and "alias" the static class method, there's an extra twist. You can't define the wrapper inline, in the class. This is because the specialization is not declared yet. You'll have to declare the wrapper; and then define it after defining the specialization:

#include <iostream>

struct S
{
    template<int x> static int f() { return x; }
    static int f1();
};

template<>
int S::f<1>()
{
    return 0;
}

inline int S::f1()
{
    return f<1>();
}

int main()
{
    std::cout << S::f<4>() << std::endl;
    std::cout << S::f<1>() << std::endl;
}

inline is needed if this actually goes into a header file, to avoid duplicate symbols at link time. If the whole thing goes into a single translation unit, you can drop inline.

Danra
  • 9,546
  • 5
  • 59
  • 117
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • `using f2=f<1>` does not compile – Danra Jan 16 '17 at 17:18
  • Looking for a way which doesn't involve wrapping. Just looking to name the a specific template method instantiation. Using the wrapping method would work but would be unDRY in case there are e.g. more parameters which are not being instantiated yet – Danra Jan 16 '17 at 17:19
0

This works:

#include <iostream>

struct S {
    template<int x> static int f() { return x; }
};

auto& g = S::f<1>;

int main() {
    std::cout << g() << std::endl;
    return 0;   
}

By using auto& we name the specific template function instantiation.

Danra
  • 9,546
  • 5
  • 59
  • 117