Explicit template creation using member template function

I have a template class with a member function of a template. I want to explicitly create an instance of the class to avoid a sharp compilation slowdown. I am using g ++ 4.1.2. I get ambiguous template specialization errors from the compiler. This is the shortest code that will reproduce the problem:

template <class T, class S > class Test { public: template< typename T1 > void* get( const T1& ); void* get(const int& ); //Specialization of the above }; typedef Test<int, double> foo; //instantiate inline template class Test<int, double>; template void* foo::get(int const&); 

I do not want to use catch-all:

 template class Test<int, double> 

because the overload of get (const int &) will not be defined for all possible explicit instances, and therefore the compiler will throw a fit for types that do not support it.

This code compiles in visual studio (without the built-in template of the previous one, which is a special extension of gcc). Could someone please shed some light on how I can compile this piece of code?

UPDATE: This is the error I get:

 g++ -c -o template.o template.cpp template.cpp:14: error: ambiguous template specialization 'get<>' for 'void* Test<int, double>::get(const int&)' template.cpp:7: error: candidates are: void* Test<T, S>::get(const int&) [with T = int, S = double] template.cpp:6: error: template<class T1> void* Test::get(const T1&) [with T1 = T1, T = int, S = double] 

UPDATE2: Thanks for the solution, but it does not compile. Specializations are not allowed inside the class. Error:

 g++ -c -o template.o template.cpp template.cpp:7: error: explicit specialization in non-namespace scope 'class Test<T, S>' template.cpp:7: error: enclosing class templates are not explicitly specialized template.cpp:8: error: 'get' is not a template function template.cpp: In instantiation of 'void* Test<T, S>::get(const T1&) [with T1 = int, T = int, S = double]': template.cpp:15: instantiated from here template.cpp:15: error: explicit instantiation of 'void* Test<T, S>::get(const T1&) [with T1 = int, T = int, S = double]' but no definition available make: *** [template.o] Error 1 
+4
source share
2 answers

I am confused by this:

I do not want to use catch-all:

 template class Test<int, double> 

because the overload get (const int &) will not be defined for all possible explicit instantiations and, therefore, the compiler will adapt to types that do not support it.

Explanation of one specialization does not affect the semantics of other specializations.

The overload get(const int&) is just a member function and it will be created for explicit and implicit specializations, like any other.

Explicit copying can slow down the compiler. It processes each instance no more than once. Unused parts of an implicit instance can be ignored, but by explicitly creating the instance, you force it to handle all of this. In any case, it is not that one instance probably took a measurable amount of time.

To execute errors in the code:

 template <class T, class S > // arguments unused class Test { public: template< typename T1 > void* get( const T1& ); void* get(const int& ); // overload of the above }; typedef Test<int, double> foo; // illegal to instantiate a template before its members are defined inline template class Test<int, double>; // "inline template" is meaningless template void* foo::get(int const&); // typedef name "foo" cannot be used here /* ^ illegal to explicitly instantiate a member of an already explicitly instantiated template */ 

Update:

The error occurs due to the absence of a template that does not take precedence over a member template.

Unfortunately, you cannot explicitly specify the template member member of the template. The workaround in this question is to partially specialize, but this will not work because you have a function template.

Workaround No. 2 - SFINAE.

  #include <boost/enable_if.hpp> #include <boost/type_traits.hpp> template< typename T1 > boost::disable_if< boost::is_same<T1,int>, void* >::type get( const T1& ); // "turn off" declaration if in conflict void* get(const int& ); // unambiguous overload of the above 

If you can’t use Boost,

  template< class T > struct disable_if_int { typedef void *type; }; template<> struct disable_if_int<int> {}; 

...

  template< typename T1 > disable_if_int< T1 >::type get( const T1& ); void* get(const int& ); // unambiguous overload of the above 
+2
source
 template <class T, class S > class Test { public: template< typename T1 > void* get( const T1& ) { return nullptr; } template <> void* get<int>(const int& ) { return nullptr; } //Specialization of the above }; typedef Test<int, double> foo; int main() { foo lols; void* innit = lols.get(1); void* bruv = lols.get("yocakes"); } 

This is just great for me on VS2010. nullptr is C ++ 0x btw, but you can just replace 0 / NULL.

0
source

All Articles