Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error when manually instantiating a template

Recently at my company we ran into an error that I am having trouble understanding why it's actually an error. To us it seems as though this should compile just fine and allow us to explicitly instantiate a template of type bar::foo.

mainy.cxx

int foo(int);
namespace bar {
  template <typename T> T foo(T a, T){return a;}
}

namespace bar {
  using ::foo;
}

template int bar::foo(int, int);

int main(){
  return 0;
}

g++ error

[csteifel@host:~/test]1047 $ g++ mainy.cxx
mainy.cxx:10: error: 'int bar::foo(int, int)' should have been declared inside 'bar'
mainy.cxx:10: error: 'int bar::foo(int, int)' is not declared in '::'

We have confirmed that this is an error in gcc 4.8, 4.4 and clang 3.7 however it appears to work with Visual Studio 2015.

We ran into this problem when we tried to instantiate std::remove but had <algorithm> included before <cstdio> and <cstdio> has in it

namespace std {
   using ::remove;
}

Any ideas on whats going on here?

like image 285
csteifel Avatar asked Apr 04 '17 20:04

csteifel


People also ask

How do I force a template instantiation?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>(float original); Template arguments may be omitted when the compiler can infer them.

Is it necessary to instantiate a template?

In order for any code to appear, a template must be instantiated: the template arguments must be provided so that the compiler can generate an actual class (or function, from a function template).

What causes a C++ template function to be instantiated?

When a function template is first called for each type, the compiler creates an instantiation. Each instantiation is a version of the templated function specialized for the type.

How many times is the template class instantiation?

Template instantiation has two forms: explicit instantiation and implicit instantiation.


1 Answers

Looks like this is related to an ancient bug in gcc, where you cannot explicitly instantiate a template by using ns::func, the only way was to do it using namespace ns { ... func; }. This was only recently fixed and with newer gcc your code will compile.

And by the way, contrary to what you are saying, your code compiles with clang 3.7.

like image 61
Pavel P Avatar answered Oct 09 '22 08:10

Pavel P