Seached for this, but can't find a similar question. If there is one please close this question.
This isn't my real code, just an example to demonstrate :-
#include <iostream>
// Normal template class with a destructor
template <class T> class Test
{
public:
~Test() { std::cout << "Normal \n";}
};
// Partial specialization for arrays
template<class T> class Test<T[]>
{
public:
~Test() { std::cout << "Array \n"; }
};
int main()
{
Test<int[3]> i;
}
When I compile this it does not call the specialized version for arrays. If I replace the template with
template<class T> class Test<T[3]>
{
public:
~Test() { std::cout << "Array \n"; }
};
Then it does call the specialization but I want this to be called for any array not just ones of a specifed size. Is there any way to write a specialization that gets used for all arrays?
Capture the size with an additional non-type parameter:
#include <iostream>
template <class T> class Test
{
public:
~Test() { std::cout << "Normal \n";}
};
template<class T, size_t N> class Test<T[N]>
{
public:
~Test() { std::cout << "Array " << N << '\n'; }
};
int main()
{
Test<int[3]> i; // Array 3
Test<int[5]> j; // Array 5
}
Related
I have a class, classB which has several functions which I would like to specialize based on an enumerator template S.
I have the following example:
#include <iostream>
#include <string>
#include <array>
typedef std::array<double, 3> vec;
enum Op {Op1, Op2, Op3};
template<class T, enum Op S=Op1>
class classA
{
public:
class innerClassA
{
public:
void foo() const
{
std::cout <<"Operation 1" << std::endl;
}
};
};
template<class T>
class classB
{
public:
template <Op S = Op1>
void myFunc()
{
typename classA<T, S>::template innerClassA myInnerClassObj;
for (int i = 0; i < 10; i++)
myInnerClassObj.foo();
}
// Other functions the I would like to able to speciallize afterwards based on template S
void myFunc2() { std::cout << "Func 2" << std::endl; }
void myFunc3() { std::cout << "Func 3" << std::endl; }
};
template<>
void classA<vec, Op2>::innerClassA::foo() const
{
std::cout << "Operation 2" << std::endl;
}
template<>
void classA<vec, Op3>::innerClassA::foo() const
{
std::cout << "Operation 3" << std::endl;
}
int main(int argc, char** argv)
{
classB<vec> obj;
obj.myFunc();
obj.myFunc2();
obj.myFunc<Op2>();
obj.myFunc<Op3>();
return 0;
}
In the above example. The function myFunc has a template parameter based on the enumerator. In the main function, I can call the specialized version based on the value of the enumerator. I would also like to do the same for the other functions,myFunc2 however, always having to put:
template <Op S = Op1>
someFunction()
is quite bothersome. Is there any other way to specify that all functions in a class have a default template based on the enumerator?
Kind regards
No, there is not, apart from macros.
#define OPFUNC template<Op S = Op1> void
OPFUNC myFunc() {}
OPFUNC myFunc2() {}
...
#undef OPFUNC
I have a template class, and at least 95% codes of it is same for all types of the template-parameter, unless a member-variable and a function should be added for one specialization.
The sample I want to get is following:
template <typename T>
class AClass {
private:
T payLoad;
public:
AClass( const T& crp_payload ) : payLoad( crp_payload ) {};
void showMe() {
cout << "Common showMe:" << payLoad << endl;
};
/*
* A lot of functions same for all specializations go here.
* I absolutely don't want to implement respectively them for
* every specializations!
*/
// specializing for int ----------------------------
// dedicated function
template <int>
void showPayload() {
cout << "AClass<int>::showPayload:" << payLoad << endl;
};
// dedicated variable, but following code can not be compiled!
template <int>
int otherPayload;
};
int main() {
AClass<int> iac( 123 );
iac.showMe();
iac.showPayload();//can not pass the compiling!
AClass<float> fac(456);
fac.showMe();
return 0;
};
My questions:
How to add merely "otherPayload" variable without re-coding entire
AClass<int>?
How to call showPayload() sinc I get a error msg when I
do it in main() as above.
Is there no way only by specializing to "revise/supplement" some
members to a class without totally re-implement it?
One possible way would be the good old inheritance:
template<class T> struct Extra {};
template<> struct Extra<int> {
int extraPayload;
void showPayload();
};
template<class T> class Class: public Extra<T> {
void showMe();
};
template<> void Class<int>::showMe() { showPayload(); }
All the specialization-specific parts are extracted in a separate class, and common methods are specialized as needed.
I think you can simply do normal specialization of the template-class:
#include <iostream>
#include <iomanip>
template <typename T>
class BaseClass
{
protected:
T payLoad;
public:
BaseClass(const T& crp_payload)
: payLoad( crp_payload )
{ }
void showMe() {
std::cout << "Common showMe:" << payLoad << std::endl;
}
/*
* A lot of functions same for all specializations go here.
* I absolutely don't want to implement respectively them for
* every specializations!
*/
};
template <typename T>
class AClass
: public BaseClass<T>
{
public:
AClass( const T& crp_payload )
: BaseClass<T>(crp_payload)
{ }
};
// specializing for int ----------------------------
template<>
class AClass<int>
: public BaseClass<int>
{
public:
AClass( int crp_payload )
: BaseClass(crp_payload)
{ }
// dedicated function
void showPayload() {
std::cout << "AClass<int>::showPayload:" << payLoad << std::endl;
}
private:
int otherPayload;
};
int main() {
AClass<int> iac( 123 );
iac.showMe();
iac.showPayload();//can not pass the compiling!
AClass<float> fac(456);
fac.showMe();
return 0;
}
I have a template method inside a template class.
I read that a method can not be specialized without specialize the class before.
But I want to factorize some of theses methods, is it possible ?
Example :
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num> class A {
private:
num n;
public:
template<typename type>
void multiplyBy(); // by 1 if <int> or 1,5 if <float>
}; // A
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<One>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
A stackoverflow related question : C++ specialization of template function inside template class
In particular this comment : C++ specialization of template function inside template class
Have I to deduct than there is no way to factorize multiplyBy(), for one for int and an other for float ?
As english is not my natural language maybe I miss something simple, maybe a workaround with partial-specialization.
Edit : put A::n in private to match even better my problem.
You might use tag dispatching:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num>
class A {
public:
num n;
private:
template<typename> struct Tag {};
void multiplyBy(Tag<int>) {
std::cout << 1.0*n.number << std::endl;
}
void multiplyBy(Tag<float>) {
std::cout << 1.5*n.number << std::endl;
}
public:
template<typename type>
void multiplyBy() {
multiplyBy(Tag<type>());
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
But I want to factorize some of theses methods, is it possible ?
You probably know that you cannot use:
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
without specializing A<One>.
You can do something along the lines of:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num, typename type = int> struct MultiplyBy {
static void doit(num n)
{
std::cout << 1.0*n.number << std::endl;
}
};
template<typename num> struct MultiplyBy<num, float> {
static void doit(num n)
{
std::cout << 1.5*n.number << std::endl;
}
};
template<typename num> class A {
public:
num n;
template<typename type>
void multiplyBy()
{
MultiplyBy<num, type>::doit(n);
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
I have checked questions that are similar. This is close, but not a duplicate.
In essence I want to call a function on a parameter pack of base classes if present. I have a C++11 way of doing this that works, but it does not feel satisfactory to me.
Can someone offer a better [i.e. better performance and less boilerplate code]:
source code:
#include <iostream>
#include <type_traits>
using namespace std;
// a class initialised with an int that can't do it
struct A
{
A(int a) : _a(a) { }
void report() const { std::cout << _a << std::endl; }
private:
int _a;
};
// a class initialised with a string that can do it
struct B
{
B(std::string s) : _b (move(s)) { }
void report() const { std::cout << _b << std::endl; }
void do_it() { std::cout << "B did it with " << _b <<"!" << std::endl; }
private:
string _b;
};
// a class initialised with an int that can do it
struct D
{
D(int d) : _d(d) { }
void report() const { std::cout << _d << std::endl; }
void do_it() { std::cout << "D did it with " << _d <<"!" << std::endl; }
private:
int _d;
};
// a class initialised with a string that can't do it
struct E
{
E(std::string s) : _e(move(s)) { }
void report() const { std::cout << _e << std::endl; }
private:
string _e;
};
// a function enabled only if T::do_it is a member function pointer
// the bool is there just to make this function more attractive to the compiler
// than the next one, below
template<class T>
auto do_it(T& t, bool)
-> typename std::enable_if<std::is_member_function_pointer<decltype(&T::do_it)>::value, void>::type
{
t.do_it();
}
// a catch-all function called when do_it<T> is not valid
// the ... is less attractive to the compiler when do_it<T>(T&, bool) is available
template<class T>
void do_it(T& t, ...)
{
}
// a compound class derived from any number of classes - I am so lazy I work hard at
// being lazy.
template<class...Templates>
struct C : public Templates...
{
// construct from a parameter pack of arbitrary arguments
// constructing each base class with one argument from the pack
template<class...Args>
C(Args&&...args)
: Templates(std::forward<Args>(args))...
{
}
// private implementation of the dispatch mechanism here...
private:
// this will call ::do_it<T>(T&, bool) if T::do_it is a member function of T, otherwise
// calls ::do_it<T>(T&, ...)
template<class T>
void may_do_it()
{
::do_it(static_cast<T&>(*this), true);
}
// calls may_do_it for the last class in the parameter pack
template<typename T1>
void multi_may_do_it()
{
may_do_it<T1>();
}
// general case for calling do_it on a parameter pack of base classes
template<typename T1, typename T2, typename...Rest>
void multi_may_do_it()
{
may_do_it<T1>();
multi_may_do_it<T2, Rest...>();
}
// calls may_do_it for the last class in the parameter pack
template<typename T1>
void multi_report() const
{
static_cast<const T1&>(*this).report();
}
// general case for calling do_it on a parameter pack of base classes
template<typename T1, typename T2, typename...Rest>
void multi_report() const
{
static_cast<const T1&>(*this).report();
multi_report<T2, Rest...>();
}
// the functions we actually wish to expose here...
public:
// disptach T::do_it for each valid T in base class list
void do_it() {
multi_may_do_it<Templates...>();
}
// dispatch T::report, which must exist for each base class
void report() const {
cout << "-- all base classes reporting:" << endl;
multi_report<Templates...>();
cout << "-- all base classes reported" << endl;
}
};
int main()
{
C<A,B, D, E> c(10, "hello", 7, "goodbye");
c.report(); // all base classes must report
c.do_it(); // all base classes that can do_it, must.
return 0;
}
output:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
-- all base classes reporting:
10
hello
7
goodbye
-- all base classes reported
B did it with hello!
D did it with 7!
I think this is about as boilerplate-free as you can make it.
// a function enabled only if T::do_it is a member function pointer
template<class T>
auto do_it(T* t)
-> typename std::enable_if<std::is_member_function_pointer<decltype(&T::do_it)>::value, void>::type
{
t->do_it();
}
// a catch-all function called when do_it<T> is not valid
// the const void * is less attractive to the compiler when do_it<T>(T*) is available
template<class T>
void do_it(const void *)
{
}
// a compound class derived from any number of classes - I am so lazy I work hard at
// being lazy.
template<class...Templates>
struct C : public Templates...
{
//constructor omitted
private:
using expander = int[];
public:
// disptach T::do_it for each valid T in base class list
void do_it() {
(void) expander{ 0, (::do_it<Templates>(this), 0)...};
}
// dispatch T::report, which must exist for each base class
void report() const {
cout << "-- all base classes reporting:" << endl;
(void) expander{ 0, (Templates::report(), 0)...};
cout << "-- all base classes reported" << endl;
}
};
Demo.
Can someone please explain me why is this not compiling...the specialized function of a specialized class ???
In the specialized version of the templated class the specialized function is not compiling.
#include<iostream>
using namespace std;
//Default template class
template<typename T>
class X
{
public:
void func(T t) const;
};
template<typename T>
void X<T>::func(T b) const
{
cout << endl << "Default Version" << endl;
}
//Specialized version
template<>
class X<int>
{
public:
void func(int y) const;
};
template<>
void X<int>::func(int y)
{
cout << endl << "Int Version" << endl;
}
int main()
{
return 0;
}
An explicit specialization of a class template is a concrete class, not a template, so you can (or rather, should) just write:
// template<>
// ^^^^^^^^^^
// You should not write this
void X<int>::func(int y) const
// ^^^^^
// And do not forget this!
{
cout << endl << "Int Version" << endl;
}
Thus leaving out the template<> part.
Also, mind the fact that your func() function is const-qualified in the declaration - so you have to use the const qualifier even in the defintion.
Here is a live example.
I think you left off the trailing const modifier