I would like a class to have a function with a template argument, and based on that template argument a particular member variable is manipulated.
For example, if function template specialization were allowed, then something like this:
struct A
{
struct M1 {};
struct M2 {};
// Function template specialization not allowed :(
template<typename M>
void addM(M const &m);
template<>
void addM(M1 const &m)
{
m1_vec_.push_back(m);
}
template<>
void addM(M2 const &m)
{
m2_vec_.push_back(m);
}
std::vector<M1> m1_vec_;
std::vector<M2> m2_vec_;
};
Any ideas? I feel like I'm missing something simple but can't quite put my finger on it.
Just overload them :
struct A
{
struct M1 {};
struct M2 {};
void addM(M1 const &m)
{
m1_vec_.push_back(m);
}
void addM(M2 const &m)
{
m2_vec_.push_back(m);
}
std::vector<M1> m1_vec_;
std::vector<M2> m2_vec_;
};
If you do not wish to duplicate addM's code, you can just abstract the vector choice behind another function :
struct A
{
struct M1 {};
struct M2 {};
template <class T>
void addM(T const &m)
{
getVec<T>().push_back(m);
}
std::vector<M1> m1_vec_;
std::vector<M2> m2_vec_;
private:
template<class T>
std::vector<T> &getVec();
};
template <>
std::vector<A::M1> &A::getVec() { return m1_vec_; }
template <>
std::vector<A::M2> &A::getVec() { return m2_vec_; }
I got a BaseType which is templated and want to inheritance it with an ArrayItem class. Since i want to use them as stencil for memory i want the ArrayItem class to know which type we have. So i'd like to specialize the constructor for some of the Template values for example long long.
template<typename T>
class ArrayItem : public BaseType<T>
{
public:
inline ArrayItem(T& t);
inline ETypes getType();
private:
ETypes m_type;
};
And the hpp should look like this:
template <typename T>
ArrayItem<T>::ArrayItem (T& t): BaseType(t)
{
}
template <>
ArrayItem<long long>::ArrayItem(long long& t) : BaseType<long long>(t) // this
{
m_type = INT;
}
template<typename T>
inline ETypes ArrayItem<T>::getType()
{
return m_type;
}
But the how do i do this specialization here?
enum ETypes
{
INT,
BOOL,
OBJECT,
ARRAY,
DOUBLE,
STRING
};
template <typename T>
class BaseType
{
public:
BaseType();
explicit BaseType(T& t);
protected:
union DataUnion
{
T data;
size_t size; //to make it at least 64bit
explicit DataUnion(T& t);
} m_data;
};
template <typename T>
BaseType<T>::DataUnion::DataUnion(T& t)
{
this->data = t;
}
template <typename T>
BaseType<T>::BaseType(T& t) : m_data(t) {}
template<typename T>
class ArrayItem : public BaseType<T>
{
public:
explicit inline ArrayItem(T& t);
inline ETypes getType();
private:
ETypes m_type;
};
template <typename T>
ArrayItem<T>::ArrayItem (T& t): BaseType<T>(t)
{
}
template <>
ArrayItem<long long>::ArrayItem(long long& t) : BaseType<long long>(t) // this
{
m_type = INT;
}
template<typename T>
inline ETypes ArrayItem<T>::getType()
{
return m_type;
}
int main()
{
long long somenumber = 1234;
ArrayItem<long long> item(somenumber);
if(item.getType() == INT)
std::cout<< "inttype";
//after this we can stancil the ptr to a
//BaseType<long long> since we know it's a long here
}
What you have looks right to me, outside of not providing the template arguments to BaseType for the typical case.
Here's a simple demo:
#include <iostream>
template <typename T>
struct B { };
template <typename T>
struct D : B<T> {
D(T );
};
template <typename T>
D<T>::D(T )
: B<T>()
{
std::cout << "def\n";
}
template <>
D<long>::D(long )
: B<long>()
{
std::cout << "hi\n";
}
int main()
{
D<int> i(4); // prints def
D<long> l(5); // prints hi
}
Given the following declaration:
template<class T>
class A {
void run(T val) {
val.member ...
}
}
This code works fine if no pointers are used:
A<Type> a;
Type t;
a.run(t);
But using a pointer results in an error:
A<Type*> a;
Type* t = new Type();
a.run(t);
error: request for member ‘member’ which is of non-class type ‘T*’
Obviously in this case the member must be accessed via ->. What's the best way to handle this?
I found a solution on SO: Determine if Type is a pointer in a template function
template<typename T>
struct is_pointer { static const bool value = false; };
template<typename T>
struct is_pointer<T*> { static const bool value = true; };
...
if (is_pointer<T>::value) val->member
else val.member
But this is very verbose. Any better ideas?
You could use a simple pair of overloaded function templates:
template<typename T>
T& access(T& t) { return t; }
template<typename T>
T& access(T* t) { return *t; }
And then use them this way:
access(val).member = 42;
For instance:
template<typename T>
struct A
{
void do_it(T& val)
{
access(val).member = 42;
}
};
struct Type
{
int member = 0;
};
#include <iostream>
int main()
{
A<Type> a;
Type t;
a.do_it(t);
std::cout << t.member << std::endl;
A<Type*> a2;
Type* t2 = new Type(); // OK, I don't like this, but just to show
// it does what you want it to do...
a2.do_it(t2);
std::cout << t2->member;
delete t2; // ...but then, don't forget to clean up!
}
Here is a live example.
The best idea is probably to specialize your class for pointer types.
template<class T>
class A{ ...};
template<>
class A<T*> { //implement for pointers
};
If you feel that this is too verbose, you can use overload a get_ref function:
template<class T> T& get_ref(T & r) {return r;}
template<class T> T& get_ref(T* r) {return *r;}
template<class T>
class A {
void do(T val) {
get_ref(val).member ...
}
}
template <typename T, typename C>
class CSVWriter{
template <typename PrinterT>
void write(std::ostream& stream, const PrinterT& printer){
}
};
I want to check whether there exists at least two overloads PrinterT::operator()(T*) and PrinterT::operator()(C*)
PrinterT may or may not inherit from std::unary_function
What concept Checking Classes I need to use here ?
(I am not using C++11)
You can use something like that
#include <iostream>
#include <boost/concept/requires.hpp>
#include <boost/concept/usage.hpp>
template <class Type, class Param>
class has_operator_round_brackets_with_parameter
{
public:
BOOST_CONCEPT_USAGE(has_operator_round_brackets_with_parameter)
{
_t(_p);
}
private:
Type _t;
Param _p;
};
struct X {};
struct Y {};
struct Test1
{
void operator() (X*) const { }
};
struct Test2: public Test1
{
void operator() (X*) const { }
void operator() (Y*) const { }
};
template <class T, class C>
struct CSVWriter
{
template <class PrinterT>
BOOST_CONCEPT_REQUIRES(
((has_operator_round_brackets_with_parameter<PrinterT, T*>))
((has_operator_round_brackets_with_parameter<PrinterT, C*>)),
(void)) write(std::ostream& stream, const PrinterT& printer)
{
}
};
int main()
{
CSVWriter<X, Y> w;
// w.write<Test1>(std::cout, Test1()); // FAIL
w.write<Test2>(std::cout, Test2()); // OK
return 0;
}
I want to automatically choose the right pointer-to-member among overloaded ones based on the "type" of the member, by removing specializations that accept unconcerned members (via enable_if).
I have the following code:
class test;
enum Type
{
INT_1,
FLOAT_1,
UINT_1,
CHAR_1,
BOOL_1,
INT_2,
FLOAT_2,
UINT_2,
CHAR_2,
BOOL_2
};
template<typename T, Type Et, typename func> struct SetterOk { static const bool value = false; };
template<typename T> struct SetterOk<T,INT_1,void (T::*)(int)> { static const bool value = true; };
template<typename T> struct SetterOk<T,FLOAT_1,void (T::*)(float)> { static const bool value = true; };
template<typename T> struct SetterOk<T,UINT_1,void (T::*)(unsigned int)> { static const bool value = true; };
template<typename T> struct SetterOk<T,CHAR_1,void (T::*)(char)> { static const bool value = true; };
template<typename T> struct SetterOk<T,BOOL_1,void (T::*)(bool)> { static const bool value = true; };
template<typename T> struct SetterOk<T,INT_2,void (T::*)(int,int)> { static const bool value = true; };
template<typename T> struct SetterOk<T,FLOAT_2,void (T::*)(float,float)> { static const bool value = true; };
template<typename T> struct SetterOk<T,UINT_2,void (T::*)(unsigned int, unsigned int)> { static const bool value = true; };
template<typename T> struct SetterOk<T,CHAR_2,void (T::*)(char,char)> { static const bool value = true; };
template<typename T> struct SetterOk<T,BOOL_2,void (T::*)(bool,bool)> { static const bool value = true; };
template <bool, class T = void> struct enable_if {};
template <class T> struct enable_if<true, T> { typedef T type; };
template<typename T, Type Et>
struct Helper
{
template<typename U>
static void func(U method, typename enable_if<SetterOk<T,Et,U>::value>::type* dummy = 0)
{
}
};
class test
{
public:
void init()
{
Helper<test,INT_2>::func(&test::set);
}
void set2(int);
void set(int);
void set(int,int);
void set(float,float);
};
int main()
{
test t;
t.init();
return 0;
}
I'm expecting it to choose the right function between all possible. The problem is that the compiler says "cannot deduce template argument as function argument is ambiguous".
It seems I don't know how to use enable_if, because if so the compiler would only allow the specialization if the specified function has the right type...
Note that I want to have C++03 solutions (if possible) - my code must compile on some old compilers.
Thanks in advance
You can never refer to an overloaded function without disambiguating it (means: static_casting it to the correct type). When you instantiate Helper::func the type of the function argument cannot be known without ever disambiguating it.
The reason it doesn't compile is quite simply that there are several different overloaded functions and it doesn't know which one you mean. Granted, only one of these (void set(int,int)) would actually compile, given the specialization Helper<test,INT_2>. However, this is not enough for the compiler to go on.
One way of getting this to compile would be to explicitly cast &test::set to the appropriate type:
Helper<test,INT_2>::func(static_cast<void (test::*)(int,int)>(&test::set));
Another way would be to use explicit template specialization:
Helper<test,INT_2>::func<void (test::*)(int,int)>((&test::set));
Either way, you need to let the compiler know which of the set functions you are trying to refer to.
EDIT:
As I understand it, you want to be able to deduce, from the use of a Type, which function type should be used. The following alternative achieves this:
template<typename T, Type Et> struct SetterOK{};
template<typename T> struct SetterOK<T,INT_1> {typedef void (T::*setter_type)(int);};
template<typename T> struct SetterOK<T,FLOAT_1> {typedef void (T::*setter_type) (float);};
// ...
template<typename T> struct SetterOK<T,INT_2> {typedef void (T::*setter_type)(int,int);};
// ....
template<typename T, Type Et>
struct Helper
{
template<typename U>
static void func(U method)
{
}
};
class test
{
public:
void init()
{
Helper<test,INT_2>::func<SetterOK<test,INT_2>::setter_type >(&test::set);
}
void set2(int);
void set(int);
void set(int,int);
void set(float,float);
};
int main()
{
test t;
t.init();
return 0;
}
ADDITIONAL EDIT:
A thought just occurred to me. In this special case which you've done, where U is SetterOK::setter_type, things can be simplified further by completely removing the template arguments for func:
static void func(typename SetterOK<T,Et>::setter_type method)
{
}
This would make the init method a simpler:
void init()
{
Helper<test,INT_2>::func(&test::set);
}