Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is redeclaring a template member function allowed in C++?

Tags:

c++

class test{
 public:
 int call();
};

int test::call();

int main(){return 0;}

The above will not compile, with this error:

error: declaration of 'int test::call()' outside of class is not definition 

However, the same code is allowed if templates are used as such:

class test{
 public:
 template<class T>
 int call();
};

template int test::call<int>(); // what's the point of this line?

template <class T>
int test::call(){
  T in = 5;
  return in;
}

int main(){
 test t;
 
 return 0;
}

I have 2 questions on this:

1- What's the point of the re-declaration? I have seen similar code in other projects.

2- Why does it compile and my first code snippet won't?

like image 566
Dan Avatar asked Mar 02 '23 12:03

Dan


1 Answers

This is not a declaration, but a definition. This is called an explicit template instantiation of a function template.

This forces the compiler to instantiate the int version in your case. You could also add explicit instantiation for many types:

class test{
 public:
 template<class T>
 int call() { return 0; }
};

template int test::call<int>();
template int test::call<float>();

It is useful to make compilation faster or control visibility of instantiation requirements by controlling when instantiation happen. This is often coupled with the extern template feature:

// ------------------
// ----- test.h -----
// ------------------
class test{
 public:
 template<class T>
 int call();
};

// Here, we tell the compiler that the instantiation exists somewhere
// That somewhere may not visible, so the compiler won't try to instantiate it
extern template int test::call<int>();
extern template int test::call<float>();


// ------------------
// ---- test.cpp ----
// ------------------

#include "test.h"

// define the template in the cpp only
template <class T>
int test::call(){
  T in = 5;
  return in;
}

// provide definitions for the instantiations:
template int test::call<int>();
template int test::call<float>();
like image 137
Guillaume Racicot Avatar answered Mar 17 '23 11:03

Guillaume Racicot