I'm new to c++ and Im learning to use templates .
I want to make a template class with 2 template parameters,and to specialize a single member function from the class, for the case where the second template parameter is a vector templated on a pointer type of the first parameter. I think an example of what I tried will be more clear :
//Container.h:
template<class T , class CONT >
class Container {
private:
CONT container;
T someData;
public:
void foo();
};
and the specilization for std::vector I tried is:
//Container.cpp
template<class T>
void Container<T, std::vector<T*> > ::foo(){
cout << "specialized foo: " << container.pop_back();
}
template<class T, class CONT >
void Container<T, CONT > ::foo(){
cout << "regular foo: " << container.pop_back());
}
but I get these erors:
error C3860: template argument list following class template name must list parameters in the order used in template parameter list
error C2976: 'Container<T,CONT>' : too few template argument
the usage of the Container class has to be that the 1st parameter is some type , and second is an STL container, vector or list. for example :
Container<int, vector<int*> > c;
c.foo();
what am I dong wrong ?
Correct syntax to define a member function in Class template is
template<class T, class CONT >
void Container<T, CONT>::foo()
{
cout << "specialized foo:" ;
}
foo() function is not overloaded and redefined. Redefinition of foo() function also gives error. You can't overload function on the basis of return type.
The specialization of std::vector is incorrect.
<< operator should also be overloaded You can'y use it directly like this
cout << container.pop_back();
You could use policy based design. Now there are many variations on this, but a simple example goes like so
#include <iostream>
#include <vector>
using namespace std;
template<typename T, class CONT>
struct foo_policy {
static inline void execute() {
cout << "regular foo: \n" ;
}
};
template<typename T>
struct foo_policy<T, std::vector<T*>> {
static inline void execute() {
cout << "specialized foo: \n" ;
}
};
template<class T , class CONT >
class Container
{
private:
CONT container;
T someData;
public:
void foo()
{
foo_policy<T, CONT>::execute();
}
};
int main()
{
Container<int, std::vector<int>> a;
Container<int, std::vector<int*>> b;
a.foo();
b.foo();
return 0;
}
Here's a demo. In another scenario you could be deriving Container from the foo_policy class and using the base member's function (but there a bit more complex implications there)
Related
I have a templated class, for which I want to specialize one of the methods for integral types. I see a lot of examples to do this for templated functions using enable_if trait, but I just can't seem to get the right syntax for doing this on a class method.
What am I doing wrong?
#include <iostream>
using namespace std;
template<typename T>
class Base {
public:
virtual ~Base() {};
void f() {
cout << "base\n";
};
};
template<typename Q>
void Base<std::enable_if<std::is_integral<Q>::value>::type>::f() {
cout << "integral\n";
}
template<typename Q>
void Base<!std::enable_if<!std::is_integral<Q>::value>::type>::f() {
cout << "non-integral\n";
}
int main()
{
Base<int> i;
i.f();
Base<std::string> s;
s.f();
return 0;
}
the above code does not compile:
main.cpp:16:60: error: type/value mismatch at argument 1 in template parameter list for ‘template class Base’
16 | void Base<std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^
main.cpp:16:60: note: expected a type, got ‘std::enable_if<(! std::is_integral<_Tp>::value)>::type’
main.cpp:21:61: error: type/value mismatch at argument 1 in template parameter list for ‘template class Base’
21 | void Base<!std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^
main.cpp:21:61: note: expected a type, got ‘! std::enable_if<(! std::is_integral<_Tp>::value)>::type’
main.cpp:21:6: error: redefinition of ‘template void f()’
21 | void Base<!std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:16:6: note: ‘template void f()’ previously declared here
16 | void Base<std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Another alternative is if constexpr (C++17):
template<typename T>
class Base
{
public:
virtual ~Base() = default;
void f() {
if constexpr(std::is_integral<T>::value) {
std::cout << "integral\n";
} else {
std::cout << "non-integral\n";
}
}
};
Some fixes are required to your code.
First, this isn't partial specialization. If it was specialization then you could only specialize the whole class template not just one method of it.
You placed the ! in the wrong place. std::enable_if<....>::type is a type, !std::enable_if<....>::type does not make sense. You want to enable one function when std::is_integral<T>::value and the other if !std::is_integral<T>::value.
You can write two overloads like this:
#include <iostream>
using namespace std;
template<typename T>
class Base {
public:
virtual ~Base() {};
template<typename Q = T>
std::enable_if_t<std::is_integral<Q>::value> f() {
cout << "integral\n";
}
template<typename Q = T>
std::enable_if_t<!std::is_integral<Q>::value> f() {
cout << "non-integral\n";
}
};
int main()
{
Base<int> i;
i.f();
Base<std::string> s;
s.f();
return 0;
}
The SFINAE is on the return type. Q is just to have a template argument (required for SFINAE). Either std::is_integral<T>::value is true or not and only one of the two overloads is not a substitution failure. When it is not a substitution failure then std::enable_if_t< ...> is void.
SFINAE won't help you here, since f is not a template function.
You could use concepts for this though. C++20 needed for using this feature:
#include <iostream>
#include <concepts>
template<typename T>
class Base {
public:
~Base() {};
void f() requires std::integral<T>
{
std::cout << "integral\n";
}
void f() requires !std::integral<T>
{
std::cout << "non-integral\n";
}
};
These are overloads, not specializations. You need to have the two overloads in the class declaration as well, otherwise you can't write these two declarations. At that point, it's likely better to have the body of the functions inside the class declaration; SFINAE guarantees that only one of them will be active.
I'm trying to write a very simple specialized class template that has a member variable and can print that member variable differently in specialized situations. I know the example is pretty useless, but it illustrates the question pretty well.
When specializing class templates it seems that the specializations of the class don't share the same member variables, so the following code won't compile...
#include <iostream>
#include <string>
// Class template
template <typename T>
struct S
{
S(const T& t)
: t(t)
{}
void print()
{
std::cout << t << std::endl;
}
private:
T t;
};
// Specialization
template <>
struct S<std::string>
{
void print()
{
// ERROR: "t" is not defined in this context
std::cout << "string: " << t << std::endl;
}
};
This suggests that I would need to write a separate constructor for every specialization and have a separate member variable t for each specialization which feels like it would quickly become a lot of duplicated code and effort if I have many specializations.
If what I am saying is true, then is it bad practice to use member variables in specialized class templates altogether? Are there any alternatives that result in less code duplication?
Please also look at #0x499602D2's answer, it is simpler and works for many practical cases.
You are correct, the specializations are basically totally independet from each other and the original template, so you would have to write everything new. A way to get around that would be to use inheritance.
#include <iostream>
#include <string>
// Class template
template <typename T>
struct Base
{
Base(const T& t)
: t(t)
{}
virtual void print()
{
std::cout << t << std::endl;
}
protected:
T t;
};
template<class T>
struct S: Base<T> {
};
// Specialization
template <>
struct S<std::string>: Base<std::string>
{
void print() override
{
std::cout << "string: " << t << std::endl;
}
};
Since you are only specializing a single template parameter, you can explicitly specialize the member function instead of the entire class:
template <>
void S<std::string>::print()
{
std::cout << "string: " << t << std::endl;
}
Another possible solution is tag-dispatcing
template <typename T>
struct S
{
private:
T t;
void print_helper (std::true_type) // T is std::string
{ std::cout << "string: " << t << std::endl; }
void print_helper (std::false_type) // T isn't std::string
{ std::cout << t << std::endl; }
public:
S (T const & t0) : t{t0}
{ }
void print ()
{ print_helper(std::is_same<T, std::string>{}); }
};
Another way to do it is to use a helper function. This will let you do partial template specialization kind of, working around the issue noted by #0x499602D2. What we're doing is having the templated function call a helper function and the helper function is doing all the specialization.
I added another template parameter into there to show that this solution kind of works for partial template specialization. Notice that the templated helper function is full-specialized, not partially. You can't partially specialize a function. This can be useful in cases when the class template has more template parameters that you can't specialize (UNUSED_T) but the function that you do want to specialize can be fully specialized (print_it doesn't need the UNUSED_T).
#include <iostream>
#include <string>
// This is the helper function for all types T...
template <typename T>
void print_it(T t) {
std::cout << t << std::endl;
}
// ... except for std::string, it will run this one.
template <>
void print_it<std::string>(std::string t) {
std::cout << "string: " << t << std::endl;
}
// Class template, UNUSED is there just to show that
// this works for partial template specialization.
template <typename T, typename UNUSED_T>
struct S {
S(const T& t) : t(t) {}
void print() {
// You can remove the <T> because
// the compiler will figure it out for you.
print_it<T>(t);
}
prviate:
T t;
UNUSED_T unused;
};
int main() {
S<uint, char> x(5);
x.print(); // OUTPUT: 5
S<std::string, char> y("foo");
y.print(); // OUTPUT: string: foo
}
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
I am kind of C++ newbie, especially when dealing with templates. I have a template class "Foo" that is intended to take different structures as template parameters. I need also to have a member function of the class that works differently depending on the type template parameter, so I specialise such a function. The general picture would be as follows
struct A
{
float paramOfA;
};
struct B
{
float paramOfB;
};
template <typename T>
class Foo
{
public:
void doSomethingOnType(T& arg);
//...more functions and stuff...
};
// function specialisation for A's
template<> void Foo<A>::doSomethingOnType(A& a){
//do something on member of A
a.paramOfA = ...;
std::cout<< "I've done something on a's member..."<<std::endl;
}
// function specialisation for B's
template<> void Foo<B>::doSomethingOnType(B& b){
//do something on member of B
b.paramOfB = ...;
std::cout<< "I've done something on b's member..."<<std::endl;
}
So far so good, right? Imagine that now I have a structure C that derives from B:
struct C:B
{
float paramOfC;
};
Now, when I instantiate a Foo object that takes C structure template type, I would want the function "doSomethingOnType" to keep the same behaviour of the function for B types on C's member that derives from B (paramOfB), eventhough I haven't specialised such a function for C structure types. For instance
Foo<C> o;
C oneC;
o.doSomethingOnType(oneC);
I am sure that when executing the above piece of code, the function will take any implementation given in the templated class, not in the specialised version for B. But I really want to keep the latter implementation of the function when using C types since, being C derived from B, it would make a lot of sense to me as well as saving me time from having to write more lines of code for a function specialisation for C's that has the same behaviour than for B (imagine that B has 50 members instead of a single one). Is it possible to do so without, as I said, specialising the function for C structure types?
Thanks a lot in advance for any help!
Really excited to ask me first question in stackoverflow :-)
You can do some hook thing in general template function, though I hate it....
these code can as following:
template <typename T>
class Foo {
public:
void doSomethingOnType(T& arg)
{
if (dynamic_cast<B*>(&arg) != NULL) {
Foo<B> fb;
fb.doSomethingOnType(arg);
} else {
std::cout << "I've done something on Foo's member..." << std::endl;
}
}
};
Although How do you force a templatization to match a base class? is an elegant solution if your function takes an instance of T as a parameter, I would like to introduce several ways if it does not:
TestCase
class A1 {};
class A2:public A1 {};
class B{};
class C{};
Wrapped Function
This might be the simplest solution:
template<typename T>
class Bar
{
public:
void fun()
{
fun_impl((T*)(0));
}
void fun_impl( A1* const)
{
cout << "A1" << endl;
}
void fun_impl(B* const)
{
cout << "B" << endl;
}
void fun_impl(void*)
{
cout << "Neither A nor B" << endl;
}
};
Bar<A2>().fun(); // A1
Bar<B>().fun(); // B
Bar<C>().fun(); // Neither A nor B
Because the precedence of fun_impl which exactly matches(or as an accessible base class of) the type > those which requires void* conversion, the correct version will be enabled.
(NOTE: This is true on clang3.7 and gcc5.3, but I din't refer to standard)
However, if we haveclass A3: private A1, an error will be raised during the compilation of Bar<A3>().fun().
The following two solutions require C++11:
Partial Specialization of Class Template
template<typename T, bool = std::is_base_of<A1, T>::value,
bool = std::is_base_of::value >
struct Foo
{
void fun();
}; //Main Version
template<typename T>
struct Foo<T,false,false>
{
void fun();
}; //Specialization of Neither A nor B
template<typename T>
void Foo<T,false,false>::fun()
{
cout << "neither A nor B" << endl;
}
template<typename T>
struct Foo<T,true,false>
{
void fun();
}; //Specialization of A
template<typename T>
void Foo<T,true,false>::fun()
{
cout << "A" << endl;
}
template<typename T>
struct Foo<T, false, true>
{
void fun();
}; //Specialization of B
template<typename T>
void Foo<T,false,true>::fun()
{
cout << "B" << endl;
}
Foo<A2>().fun(); //A
Foo<B>().fun(); //B
Foo<C>().fun(); //Neither A nor B
Foo<APrivate>().fun(); //A
SFINAE
If you don't want to specialize the whole class, maybe SFINAE in one class could be the best choice:
namespace
{
class Helper1 {};
class Helper2 {};
} // Helper classes to avoid ambiguity
template<typename T>
class Foo
{
public:
template<typename TIn= T, typename U= typename std::enable_if<std::is_base_of<A1, TIn>::value>::type >
void fun(Helper1 = Helper1())
{
cout << "A" << endl;
}
template<typename TIn=T ,typename U = typename std::enable_if<std::is_base_of<B, TIn>::value>::type >
void fun(Helper2 = Helper2())
{
cout << "B" << endl;
}
template<typename TIn = T, typename = typename std::enable_if<!std::is_base_of<A1,TIn>::value>::type ,
typename = typename std::enable_if<!std::is_base_of<B,TIn>::value>::type >
void fun()
{
cout << "Neither A nor B" << endl;
}
};
In the case above a function will be instantiated only if it matches some certain conditions. Since three void fun() are not allowed in one class, helper classes are required.
I've searched for this question and I can't find anything on it. Is there a better way to query something like this in Google or can anyone provide a link or links or a fairly detailed explanation? Thanks!
EDIT: Here's an example
template< typename T, size_t N>
struct Vector {
public:
Vector() {
this->template operator=(0);
}
// ...
template< typename U >
typename boost::enable_if< boost::is_convertible< U, T >, Vector& >::type operator=(Vector< U, N > const & other) {
typename Vector< U, N >::ConstIterator j = other.begin();
for (Iterator i = begin(); i != end(); ++i, ++j)
(*i) = (*j);
return *this;
}
};
This example is from the ndarray project on Google Code and is not my own code.
Here is an example where this->template is required. It doesn't really match the OP's example though:
#include <iostream>
template <class T>
struct X
{
template <unsigned N>
void alloc() {std::cout << "alloc<" << N << ">()\n";}
};
template <class T>
struct Y
: public X<T>
{
void test()
{
this->template alloc<200>();
}
};
int main()
{
Y<int> y;
y.test();
}
In this example the this is needed because otherwise alloc would not be looked up in the base class because the base class is dependent on the template parameter T. The template is needed because otherwise the "<" which is intended to open the template parameter list containing 200, would otherwise indicate a less-than sign ([temp.names]/4).
It used to disambiguation, and
// maybe: (handle->appendArray < 13) > (myarray);
handle->appendArray<13>(myarray);
Maybe some compilers can deduce it automatically.
When extending a class that depends on a template parameter, this kind of become a dependent name.
The problem is that while performing two phase name lookup, the compiler can't know where he can find the function hello. He cannot know it comes from the parent. Because template specialization is a thing, Base<int> and Base <double> could be two completely different clas swith different functions and members.
With the this keyword added, the compiler know that hello must be a member function.
Without that, it could be either a member function or non-member function.
#include <iostream>
template <class T>
class Base {
public:
void hello() {std::cout << "hello\n";}
void hello1() {std::cout << "hello1\n";}
template <unsigned N>
void hello2() {std::cout << "hello2<" << N << ">()\n";}
};
template <class T>
class Drivered: public Base<T> {
public:
using Base<T>::hello;
void test()
{
hello();
this->hello1();
this->template hello2<200>();
}
};
int main() {
Drivered<int> d;
d.test();
}
【1】https://stackoverflow.com/a/39667832/4268594