Explicit template specialization cannot have a storage class - member method specialization - c++

Say I have the following code in Visual Studio
class foo
{
public:
template<typename t>
void foo_temp(int a , t s_)
{
std::cout << "This is general tmeplate method";
}
template<>
static void foo_temp(int a , int s)
{
std::cout << "This is a specialized method";
}
};
int main()
{
foo f;
f.foo_temp<std::string>(12,"string");
}
Now I am attempting to covert this into GCC. Going through other questions on SO I noticed that in GCC member methods cannot be specialized if the class is not specialized. I therefore came up with this solution
class foo
{
public:
template<typename t>
void foo_temp(int a , t s_)
{
std::cout << "This is general template method";
}
};
template <>
/*static*/ void foo::foo_temp<int>(int a, int value) {
std::cout << "Hello world";
}
Now this seems to do the trick however when I include the static keyword into the statement i get the error
explicit template specialization cannot have a storage class
Now this thread talks about it but I am still confused on how I could apply that here. Any suggestions on how I can make the last method static ? Also I am still confused as to why templated methods cant be static in GCC ?
This is the visual studio code
class foo
{
public:
template<typename t>
void foo_temp(int a , t s_)
{
std::cout << "This is general tmeplate method";
}
template<>
static void foo_temp(int a , int s)
{
std::cout << "This is a specialized method";
}
};
int main()
{
foo f;
f.foo_temp<std::string>(12,"string");
}

Any suggestions on how I can make the last method static?
You can't; it's unsupported by the language.
Also I am still confused as to why templated methods cant be static in GCC?
They can; they just can't be both static and non-static. Example:
struct foo {
template<typename T>
void bar() {}
template<typename T>
static void baz() {}
};
int main() {
foo f;
f.template bar<void>();
foo::baz<void>();
}
It's very confusing to me why you must have a static specialization of a (non-static) template member function. I would seriously re-evaluate this code for sanity.
Note, to the question in the comments, it is not possible to have a template specialization of a static member function, because it is not possible to have a template specialization of a member function in this situation at all. (Use overloading instead.)
struct foo {
template<typename T, typename U>
static void bar(T, U) {}
// Error, you'd need to also specialize the class, which requires a template class, we don't have one.
// template<>
// static void bar(int, int) {}
// test.cpp:2:12: error: explicit specialization of non-template ‘foo’
// 2 | struct foo {
// | ^
// Partial specializations aren't allowed even in situations where full ones are
// template<typename U>
// static void bar<int, U>(int, U) {}
// test.cpp:14:33: error: non-class, non-variable partial specialization ‘bar<int, U>’ is not allowed
// 14 | static void bar<int, U>(int, U) {}
// | ^
// Instead just overload
template<typename U>
static void bar(int, U) {}
};

Did you try good old fashioned overloading? Don't make the static method a template at all and let overloading priority take care of picking it.

The static method isn't the problem here, the template<> declaration inside a class is the main culprit. You can't declare specialized template inside a class. you can use namespace instead:
namespace foo{
template<typename t>
void foo_temp(int a , t s_)
{
std::cout << "This is general tmeplate method";
}
template<>
void foo_temp(int a , int s)
{
std::cout << "This is a specialized method";
}
}
int main()
{
foo::foo_temp<int>(12,7);
}
Or you can use it inside class like this:
class foo
{
public:
template<typename t>
void foo_temp(int a , t s_)
{
std::cout << "This is general tmeplate method";
}
static void foo_temp(int a , int s)
{
std::cout << "This is a specialized method";
}
};
int main()
{
foo f;
f.foo_temp(12,"string");
f.foo_temp(12,6);
}
N.B: you should call both function (at least the second one) like f.foo_temp(a,b) instead of f.foo_temp<int>() in this case.

Related

template behavior for static templatized member function in the header file only

class Myclass
{
template <typename T>
static T func()
{
T obj;
return obj;
}
template<>
static int func<int>()
{
}
};
I wrote above class and tried to compile it.
I got following error:
error: explicit specialization in non-namespace scope 'class Myclass'
error: template-id 'func' in declaration of primary template
Then I moved out my static function out side the class like this:
namespace helper
{
template <typename T>
static T func()
{
T obj;
return obj;
}
template<>
static int func<int>()
{
}
}
class Myclass
{
template <typename T>
static T func()
{
helper::func<T>();
}
};
I got following error:
error: explicit template specialization cannot have a storage class
In static member function 'static T Myclass::func()':
Then of course I inline my specialized function and it worked.
namespace helper
{
template <typename T>
static T func()
{
T obj;
return obj;
}
template<>
inline int func<int>()
{
return 1;
}
}
class Myclass
{
template <typename T>
static T func()
{
helper::func<T>();
}
};
My questions are:
1) Why can't we specialize static member functions inside the class.
2) Why can't we have static template specialized functions
Honestly, the real answers to both questions are probably "because."
You can specialize a member function template, it just has to be outside of the class and cannot use the static keyword:
struct Myclass {
template <class T>
static T func() {
T obj{};
return obj;
}
};
template <>
int Myclass::func<int>() { return 42; }
Both are mostly grammatical reasons. It's just one of those things that you have to remember.
To my knowledge C++ does not allow member template specialization at class level. The specializations must be provided at namespace level, so you could declare the specialization outside the class:
// myclass.h
class MyClass
{
public:
template <class T>
void test(T )
{
std::cout << "non-specialized test" << std::endl;
}
template <class T>
static T myfunc()
{
std::cout << "non-specialized myfunc" << std::endl;
return T{};
}
};
template <>
inline void MyClass::test(double t)
{
std::cout << "specialized test" << std::endl;
}
template <>
static double MyClass::myfunc();
/*template <>
static inline void MyClass::myfunc(double )
{
std::cout << "specialized myfunc" << std::endl;
}*/
Then you provide the implementation in the source file:
// myclass.cpp
template <>
static double MyClass::myfunc()
{
std::cout << "specialized myfunc" << std::endl;
return 0.0;
}
Alternatively, you could inline myfunc() in the header file (just like test() function).
Regarding your second question, I tried it in VS2015 and it worked. The only problem is that you are missing return values.

Class template, member function definition if object is of type X?

Is it possible to create a class template with a member function definition only if the object created is of a specific type?
I've created a template class I will use for storing either int or doubles, but for doubles I would like to be able to set precision too (objects created with myclass < double> should have this functionality, but for myclass< int> there is no need for that to be present at all).
I know I can use a base class template, and create new classes "myInt", "myDouble" using that and implement the functionality only in the myDouble class, but I think it would be cleaner to define the functionality (both the function and a member variable) for doubles in the class template, if that's possible and preferable?
Let's add an example to show what I want to do:
#include <iostream>
#include <iomanip>
class commonBase{
public:
void setState(int state);
virtual void print() = 0;
private:
int _my_state;
};
template <typename T>
class generalObject : public commonBase {
public:
void value(T value);
void print(){ std::cout << "My value: " << _my_value << std::endl; }
private:
T _my_value;
};
template <typename T>
void generalObject<T>::value(T value){
_my_value = value;
}
// Is there any way do specialize only only whats different from the generalObject template?
// Here I thought I could specialize the case where a generalObject is created of <double>, but
// when I do, nothing is derived from generalObject (or at least not visible as far as I can tell)
template<>
class generalObject<double>{
public:
void setPrecision(int precision){ _my_precision = precision; }
// here I would like a special implementation of print(), which overrides the print() in generalObject
// and instead also prints according to the precision set when the object is of <double> type.
// Row below an example which doesn't work (compiler error, _my_value undefined)
void print(){ std::cout << "My value: " << std::setprecision(_my_precision) << _my_value << std::endl; }
private:
int _my_precision;
};
int main(int argc, char* argv[]){
generalObject<int> o1;
o1.value(1);
o1.print();
o1.setState(1); //inherited from the commonBase
generalObject<double> o2;
o2.setPrecision(2);
o2.value(2); //here value isn't available (compile error)
o2.print();
o2.setState(123); //also isn't available (compile error)
}
Sure.
template <typename T> class Poly;
void set_precision(Poly<double>* self, int a) {};
If you really want dot notation you can then add:
template <typename T> class Poly {
public: void set_precision(int a){::set_precision(this,a);}
...
However I think you should think about what you're trying to accomplish. If MyInt and MyDouble have different fields and different methods and different implementations, they should probably be different classes.
This can be solved using template specialization.
We first define a common template...
template< typename T >
struct myclass
{
// common stuff
};
... and specialize that for double:
template<>
struct myclass<double>
{
int precision = 10;
void setprecision( int p ){ precision = p; }
};
Now the setprecision() method can only be called for myclass<double>. The compiler will complain if we try to call it for anything else, like myclass<int>.
int main()
{
myclass<double> d;
d.setprecision( 42 ); // compiles
myclass<int> i;
i.setprecision( 42 ); // fails to compile, as expected
}
Demo.
The basic way to have a member function of a class template exist only for some template parameters is to create a specialization of the class template for those template parameters.
template<typename T>class X{
// general definition
};
template<>class X<double>{
// double-specific definition
};
The downside of this is that the specialization will need to duplicate anything that is common. One way to address this is to move the common things out to a base class template:
template<typename T>class Xcommon{
// common stuff
};
template<typename T>class X: public Xcommon<T>{
// general definition
};
template<>class X<double>: public Xcommon<double>{
// double-specific definition
};
Alternatively, you can do it the other way: put the common stuff in the derived class, and the extras in the base, and specialize the base:
template<typename T>class Xextras{
// empty by default
};
template<typename T>class X: public Xextras<T>{
// common definition
};
template<>class Xextras<double>{
// double-specific definition
};
Either way can work; which is better depends on the details.
Both these methods work for data members and member functions.
Alternatively, you can use enable_if to mean that member functions are not selected by overload resolution if the template parameter doesn't meet a required condition. This requires that the member function is itself a template.
template<typename T>class X{
template<typename U=T> // make it a template,
std::enable_if<std::is_same_v<U,double>> double_specific_function(){
// do stuff
}
};
I wouldn't recommend this option unless there is no other choice.
If the question is about a member function, then here is one of the ways to do it without class template specialization:
#include <iostream>
#include <type_traits>
template <typename T>
struct Type {
template <typename U = T,
typename = typename std::enable_if<std::is_same<U, double>::value>::type>
void only_for_double() {
std::cout << "a doubling" << std::endl;
}
};
int main() {
Type<int> n;
Type<double> d;
// n.only_for_double(); // does not compile.
d.only_for_double();
}
Example on ideone.com
If you require a data-member presence based on the template parameter, you will have to do some kind of specialization, in which case it is, probably, simpler to put the function into corresponding specialization.
EDIT: After OP made his question more specific
Here is one way to do it without extra class and getting rid of virtual functions. Hope it helps.
#include <iostream>
#include <iomanip>
template <typename T, typename Derived = void>
class commonBase {
public:
void setState(int state) {
_my_state = state;
}
void value(T value) {
_my_value = value;
}
template <typename U = Derived,
typename std::enable_if<std::is_same<U, void>::value,
void * >::type = nullptr>
void print() const {
std::cout << "My value: " << _my_value << std::endl;
}
template <typename U = Derived,
typename std::enable_if<!std::is_same<U, void>::value,
void * >::type = nullptr>
void print() const {
static_cast<Derived const *>(this)->_print();
}
protected:
T _my_value;
int _my_state;
};
template <typename T>
class generalObject : public commonBase<T> {
};
template<>
class generalObject<double> : public commonBase<double, generalObject<double>> {
private:
friend commonBase<double, generalObject<double>>;
void _print() const {
std::cout << "My value: " << std::setprecision(_my_precision) <<
_my_value << std::endl;
}
public:
void setPrecision(int precision){ _my_precision = precision; }
private:
int _my_precision;
};
int main(){
generalObject<int> o1;
o1.value(1);
o1.print();
o1.setState(1);
generalObject<double> o2;
o2.setPrecision(2);
o2.value(1.234);
o2.print();
o2.setState(123);
}
Same code on ideone.com

Invalid use of incomplete type (class method specialization)

First, I've read over many other questions and couldn't find the solution. So before marking it a duplicate, please make sure duplicate answers the question.
I'm trying to specialize F::operator() for a class C2; however, C2 has a template parameter and I want F::operator() to behave the same for all C2's.
Compiler error:
error: invalid use of incomplete type ‘struct F<C2<T> >’
void F<C2<T>>::operator()()
Also, instead of Handle& h, I tried Handle* h and received the same error.
#include<iostream>
struct C1
{
void foo()
{
std::cout << "C1 called" << std::endl;
}
};
template<typename T>
struct C2
{
void bar();
};
template<>
void C2<int>::bar()
{
std::cout << "C2<int> called" << std::endl;
}
template<typename Handle>
struct F
{
F(Handle& h_) : h(h_) {}
void operator()();
Handle& h;
};
template<>
void F<C1>::operator()()
{
h.foo();
}
template<typename T>
void F<C2<T>>::operator()()
{
h.bar();
}
int main()
{
C1 c1;
F<C1> f_c1 (c1);
f_c1();
C2<int> c2;
F<C2<int>> f_c2 (c2);
f_c2();
}
There's no such thing like a partial specialization of a member function. You'd need to first partial-specialize the entire class:
template <typename T>
struct F<C2<T>>
{
void operator()();
};
template <typename T>
void F<C2<T>>::operator()() {}
Since this is a heavy-weight solution, alternatively, you can exploit tag-dispatching:
template <typename T> struct tag {};
template <typename Handle>
struct F
{
F(Handle& h_) : h(h_) {}
void operator()()
{
call(tag<Handle>{});
}
private:
void call(tag<C1>)
{
h.foo();
}
template <typename T>
void call(tag<C2<T>>)
{
h.bar();
}
Handle& h;
};
DEMO

Partial function/method template specialization workarounds

I know partial template specialization isn't supported for functions and class methods, so my question is: What are common solutions or patterns to resolve this? Below Derived derives from Base, and both of these classes have virtual methods greet() and speak(). Foo's holds a std::array<unique_ptr<T>, N> and is used in do_something(). Foo has two template parameters: T (the class type) and N (number of elements of the std::array) If N = 2, there exists a highly optimized version of do_something(). Now assume that Foo's T parameter isn't always the base class Base. Ideally, I would like to write the following code, but it's illegal:
//ILLEGAL
template<typename T>
void Foo<T,2>::do_something()
{
arr_[0]->greet();
}
Below is the full code and my current (ugly) solution. I have to specialize do_something() twice, once for Base and once for Derived. This gets ugly if there exists multiple methods like do_something() that can be optimized on the special N=2 case, and if there exists many subclasses of Base.
#include <iostream>
#include <memory>
class Base
{
public:
virtual void speak()
{
std::cout << "base is speaking" << std::endl;
}
virtual void greet()
{
std::cout << "base is greeting" << std::endl;
}
};
class Derived : public Base
{
public:
void speak()
{
std::cout << "derived is speaking" << std::endl;
}
void greet()
{
std::cout << "derived is greeting" << std::endl;
}
};
template<typename T, int N>
class Foo
{
public:
Foo(std::array<std::unique_ptr<T>, N>&& arr) :
arr_(std::move(arr))
{
}
void do_something();
std::array<std::unique_ptr<T>, N> arr_;
};
template<typename T, int N>
void Foo<T,N>::do_something()
{
arr_[0]->speak();
}
//Want to avoid "copy-and_paste" of do_something() below
template<>
void Foo<Base,2>::do_something()
{
arr_[0]->greet();
}
template<>
void Foo<Derived,2>::do_something()
{
arr_[0]->greet();
}
int main()
{
constexpr int N = 2;
std::array<std::unique_ptr<Derived>, N> arr =
{
std::unique_ptr<Derived>(new Derived),
std::unique_ptr<Derived>(new Derived)
};
Foo<Derived, N> foo(std::move(arr));
foo.do_something();
return 0;
}
The trick is to forward implementation to an helper template class, and partial specialize that class and/or use tag dispatching:
namespace {
template<typename T, int N, bool isBase = std::is_base_of<Base, T>::value>
struct helper {
// general case:
void operator () (std::array<std::unique_ptr<T>, N>& arr_) const
{
arr_[0]->speak();
}
};
template<typename T>
struct helper<T, 2, true>
{
void operator () (std::array<std::unique_ptr<T>, 2>& arr_) const
{
arr_[0]->greet();
}
};
// You may add other specialization if required.
}
template<typename T, int N>
void Foo<T,N>::do_something()
{
helper<T, N>()(arr_);
}
There are different alternatives, depending on how other constrains in the problem one might be more appropriate than another.
The first one is to forward the request to a static function in a template class, which allows for partial specializations:
template <int N>
struct Helper {
template <typename T>
static void talk(T& t) { // Should be T const &, but that requires const members
t.speak();
}
};
template <>
struct Helper<2> {
template <typename T>
static void talk(T& t) {
t.greet();
}
}
;
Then the implementation of do_something would be:
template <typename T, int N>
void Foo<T,N>::do_something() {
Helper<N>::talk(*arr_[0]);
}
Alternatively, you can use tag dispatch to select one of multiple overloads:
template <int N> struct tag {};
template <typename T, int N>
template <int M>
void Foo<T,N>::do_something_impl(tag<M>) {
arr_[0]->speak();
}
template <typename T, int N>
void Foo<T,N>::do_something_impl(tag<2>) {
arr_[0]->greet();
}
template <typename T, int N>
void Foo<T,N>::do_something() {
do_something_impl(tag<N>());
}
Where I have created a tag-type that can be specialized for any possible N. You could also use existing tools in C++11.
Finally, if you need to do something like this for different functions, you can use inheritance, and push some of the functionality to a base that resolves the differences. This can be done by either pushing common code to a base, differences to an intermediate level and using a lower level front type that just inherits from the rest (base contains generic code, derived types specialize). Or alternatively with CRTP (base(s) contain differences, derived type generic code and pulls specific implementations from the bases.

Template specific methods

If I have a class A
template <typename T>
class A { public: void print() const; };
I can write specific version of my methode print for specific template values my doing
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
and the calling the method print will just call the code of the good implementation (of the compiler tell me if I don't have an implementation for a specific template.
Now, if I have multiples types in my class B's template
template <typename T1, typename T2>
class B { public: void print() const; };
and if I try to do the same as before, let's say for T2
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
I get an compiler error :
error: invalid use of incomplete type 'class B<T1,bool>'
error: declaration of 'class B<T1, bool>'
What am I doing wrong ?
EDIT
My real life B class contains other methods with I do not want to specify (they work in the general case)
Having a partially specified class decalred makes that those generic methods aren't natively availlable
You can't partial specialize a function/method.
But you can partial specialize the whole class:
template <typename T1, typename T2> class B;
template<typename T1> class B<T1, bool>
{
public:
void print() const { printf("B w/ type bool\n"); }
};
What am I doing wrong?
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
These member functions are like normal functions, they are not templates with un-substituted parameters, so you are just providing definitions for the symbols, which will be used when those functions get called. (And like normal functions, if those definitions are in a header and you don't declare them inline you will get multiple definitions errors for them.)
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
This is not the same, this is providing a definition for a member function of a class template partial specialization. i.e. it's a template that will be used to generate code for the member of that partial specialization, but you haven't declared any such partial specialization, so you can't define its members.
You can make it compile by defining the partial specialization first:
// primary template
template <typename T1, typename T2>
class B { public: void print() const; };
// partial specialization
template<typename T1>
class B<T1,bool> { public: void print() const; };
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
However it is often inconvenient to have to repeat the entire class template definition just to define a partial specialization for one or two members, so it might be worth taking one of the alternative designs shown in other answers.
With templates it's best to decompose each part of the specialisation into its own template function or traits class.
Here's a clean way to do what you want:
template<typename T>
const char* type_name()
{
return "unknown";
};
template<>
const char* type_name<int>()
{
return "int";
}
template<>
const char* type_name<bool>()
{
return "bool";
}
struct foo {};
template<>
const char* type_name<foo>()
{
return "my custom foo";
}
struct bar {};
template <typename T>
class A {
public:
void print() const {
cout << "A w/ type " << type_name<T>() << '\n';
}
};
int main() {
A<bool> ab;
A<int> ai;
A<foo> af;
A<bar> abar;
ab.print();
ai.print();
af.print();
abar.print();
return 0;
}
output:
A w/ type bool
A w/ type int
A w/ type my custom foo
A w/ type unknown
Program ended with exit code: 0
With tag dispatching, you might do:
#include <iostream>
template<typename A, typename B>
class X
{
private:
template <typename U> struct Tag {};
template <typename U>
void print(Tag<U>) const;
void print(Tag<bool>) const { std::cout << "bool\n"; }
void print(Tag<int>) const{ std::cout << "int\n"; }
public:
void print() const { print(Tag<B>()); }
};
int main()
{
X<void, bool>().print();
X<void, int>().print();
}