Cory Kramer
Cory Kramer

Reputation: 118021

Nested template class method syntax

If I have a class A that is templated on type T, and that class has a method Foo that is templated on type U

template <class T>
class A
{
public:
    template <class U>
    void Foo();
};

To define that function outside the class I need two template statements like so

template <class T>
template <class U>
void A<T>::Foo() {}            // this compiles

The following does not compile

template <class T, class U>
void A<T>::Foo() {}            // this does not compile

with the error

prog.cpp:10:6: error: no declaration matches ‘void A<T>::Foo()’
 void A<T>::Foo() {}
      ^~~~
prog.cpp:6:7: note: candidate is: ‘template<class T> template<class U> void A<T>::Foo()’
  void Foo();
       ^~~
prog.cpp:2:7: note: ‘class A<T>’ defined here
 class A
       ^

Is there a more terse/compact way to define both template types in a single statement like above?

Upvotes: 2

Views: 89

Answers (1)

dfrib
dfrib

Reputation: 73236

C++20: Abbreviated function templates

Is there a more terse/compact way to define both template types in a single statement like above?

As of C++20, you can make use of abbreviated function templates, which allows declaring as well (later) defining function templates in a more compact manner. This approach, however, is restricted to type template parameters that can be inferred via template argument deduction, as the placeholder types (auto or SomeConcept auto) must appear in the parameter list of an abbreviated function template declaration.

template <typename T>
struct A {
    void foo(auto);
};

template <typename T>
void A<T>::foo(auto) {}

Note that void foo(auto) is equivalent to template<typename T> void foo(T), as the former declares a function template with a single (invented) template parameter corresponding to the single placeholder type. This means that mixing of the abbreviated function template syntax and the classic function template syntax for the same entity is allowed (e.g. using one syntax for declaring it and the other syntax for defining it):

template <typename T>
struct A {
    template <typename U>
    void foo(U);
};

template <typename T>
void A<T>::foo(auto) {}

template <typename T>
struct B {
    template <typename U>
    void foo(U, auto);
};

template <typename T>
void B<T>::foo(auto, auto) {}

Upvotes: 4

Related Questions