accessing members of a templated class with variable numbers of templated arguments - c++

I have a templated class with variable numbers of templated arguments. As in these cases (I cannot afford C++11) a good practice is to create a default class that we call none and put it as default like below.
struct none {};
template<class T1=none, T2=none, T3=none>
class A{
template<class T>
double extract() { return none();}
template<>
double extract<T1>() { return m1_();}
template<>
double extract<T2>() { return m2_();}
template<>
double extract<T3> () { return m3_();}
T1 m1_;
T2 m2_;
T3 m3_;
};
At this stage I don't know how to implement a generic/templated accessor function that can access each of the templated argument.
All of the templated arguments are different so I specialized A::extract() for each of the templated arguments.
Is there any better way to do this? Any sort of tagging I can have a look at?

struct none {};
template <class T, class N>
class Holder : public N
{
protected:
T m;
typedef Holder<T, N> First;
double extractP(T*) { return m(); }
template <class X> double extractP(X*) {
return this->N::extractP(static_cast<X*>(0));
}
};
template <class T>
class Holder<T, none>
{
protected:
T m;
typedef Holder<T, none> First;
double extractP(T*) { return m(); }
template <class X> none extractP(X*) {
return none();
}
};
template <class T1 = none, class T2 = none, class T3 = none>
class A : Holder<T1, Holder<T2, Holder<T3, none> > >
{
public:
template <class T> double extract() {
return this->extractP(static_cast<T*>(0));
}
};

A similarly-named solution to n.m but more on the Boost's Variant class design.
The suggestion is to use a Variant container (a generic container for your objects) and use accessors directly on them.
#include <iostream>
#include <stdexcept>
using namespace std;
class BaseHolder
{
public:
virtual ~BaseHolder(){}
virtual BaseHolder* clone() const = 0;
};
template<typename T>
class HoldData : public BaseHolder
{
public:
HoldData(const T& t_) : t(t_){}
virtual BaseHolder* clone() const {
return new HoldData<T>(t);
}
T getData() {
return t;
}
private:
T t;
};
class Variant
{
public:
Variant() : data(0) {}
template<typename T>
Variant(const T& t) : data(new HoldData<T>(t)){}
Variant(const Variant& other) : data(other.data ? other.data->clone() : 0) {}
~Variant(){delete data;}
template<typename T>
T getData() {
return ((HoldData<T>*)data)->getData();
}
private:
BaseHolder* data;
private:
Variant& operator=(const Variant& other) { return *this;} // Not allowed
};
struct none {};
class Container{
public:
Container() : m1_(0), m2_(0), m3_(0){}
~Container() {
if(m1_)
delete m1_;
if(m2_)
delete m1_;
if(m3_)
delete m1_;
}
none extract() { return none();}
template<typename T>
void insertM1(T obj) {
m1_ = new Variant(obj);
}
template<typename T>
T extractM1() {
if(m1_ != 0)
return m1_->getData<T>();
else
throw std::runtime_error("Element not set");
}
// TODO: implement m2 and m3
Variant *m1_;
Variant *m2_;
Variant *m3_;
};
int main() {
Container obj;
char M1 = 'Z';
obj.insertM1(M1);
char extractedM1 = obj.extractM1<char>();
cout << extractedM1;
return 0;
}
http://ideone.com/BaCWSV

Your class seems to mimic std::tuple, which, unfortunately for you, was added in C++11. The good news is that you can use boost::tuple instead.
As an example of usage:
boost::tuple<std::string, double> t = boost::make_tuple("John Doe", 4.815162342);
std::cout << boost::get<0>(t) << '\n';
std::cout << boost::get<1>(t) << '\n';
Live demo

Without access to C++11, it's a bit uglier, but you can leverage Boost.Tuple:
#include <iostream>
#include <boost/tuple/tuple.hpp>
template <size_t I, typename T, typename U>
struct AccessImpl;
template <size_t I, typename T, typename U>
struct AccessImpl {
template <typename Tuple>
static T& impl(Tuple& tuple) {
typedef typename ::boost::tuples::element<I+1, Tuple>::type Next;
return AccessImpl<I+1, T, Next>::impl(tuple);
}
};
template <size_t I, typename T>
struct AccessImpl<I, T, T> {
template <typename Tuple>
static T& impl(Tuple& tuple) { return boost::get<I>(tuple); }
};
template <typename T, typename Tuple>
T& access(Tuple& tuple) {
typedef typename ::boost::tuples::element<0, Tuple>::type Head;
return AccessImpl<0, T, Head>::impl(tuple);
}
int main() {
boost::tuples::tuple<char, int, std::string> example('a', 1, "Hello, World!");
std::cout << access<std::string>(example) << "\n";
return 0;
}
This, as expected, prints "Hello, World!".

Related

Need a way to check template type and if not in the range of allowed types then have compile time error in C++

I need to have a template class where each object adds itself to a vector and based on the template type parameter(allowed only: string, int, float) add to the corresponding container. I need a way to have compile time checks for the type and based on the check add to the corresponding container and if the type is not one of the allowed types compile time error should be emitted.
Example: code
vector<myClass<int>*> intVec;
vector<myClass<float>*> floatVec;
vector<myClass<string>*> stringVec;
template<typename T>
struct myClass
{
myClass()
{
/*pseudo code
if(T == int) {
intVec.push_back(this);
}
else if(T == float) {
floatVec.push_back(this);
}
else if(T == string){
stringVec.push_back(this);
}
else {
// error
}
*/
}
T value;
}
How can I achieve this ?
In C++17 and later, you can use if constexpr and std::is_same_v, eg:
#include <type_traits>
template<typename T>
struct myClass
{
myClass()
{
if constexpr (std::is_same_v<T, int>) {
m_intVec.push_back(this);
}
else if constexpr (std::is_same_v<T, float>) {
m_floatVec.push_back(this);
}
else if constexpr (std::is_same_v<T, std::string>){
m_stringVec.push_back(this);
}
else {
// error
}
}
T value;
};
In earlier versions, you can use either template specialization or SFINAE instead, eg:
// via specialization
template<typename T>
struct myClass
{
};
template<>
struct myClass<int>
{
myClass()
{
m_intVec.push_back(this);
}
int value;
};
template<>
struct myClass<float>
{
myClass()
{
m_floatVec.push_back(this);
}
float value;
};
template<>
struct myClass<std::string>
{
myClass()
{
m_stringVec.push_back(this);
}
std::string value;
};
// via SFINAE
#include <type_traits>
template<typename T>
struct myClass
{
template<typename U = T, std::enable_if<std::is_same<U, int>::value, int>::type = 0>
myClass()
{
m_intVec.push_back(this);
}
template<typename U = T, std::enable_if<std::is_same<U, float>::value, int>::type = 0>
myClass()
{
m_floatVec.push_back(this);
}
template<typename U = T, std::enable_if<std::is_same<U, std::string>::value, int>::type = 0>
myClass()
{
m_stringVec.push_back(this);
}
T value;
};
Use specialization and a helper function, e.g.
template<typename T>
struct myClass;
inline std::vector<myClass<int>*> intVec;
inline std::vector<myClass<float>*> floatVec;
inline std::vector<myClass<std::string>*> stringVec;
template<typename T>
void add(myClass<T>*);
template<>
void add(myClass<int>* p) {
intVec.push_back(p);
}
template<>
void add(myClass<float>* p) {
floatVec.push_back(p);
}
template<>
void add(myClass<std::string>* p) {
stringVec.push_back(p);
}
template<typename T>
struct myClass
{
myClass()
{
add(this);
}
T value;
};
in addition to existing answers, you can also do it with normal function overloading
template<typename T>
struct myClass;
inline std::vector<myClass<int>*> intVec;
inline std::vector<myClass<float>*> floatVec;
inline std::vector<myClass<std::string>*> stringVec;
/* optional
template<typename T>
constexpr bool always_false = false;
template<typename T>
void add(myClass<T>*) {
static_assert(always_false<T>,"unsupported T");
}
*/
void add(myClass<int>* p) {
intVec.push_back(p);
}
void add(myClass<float>* p) {
floatVec.push_back(p);
}
void add(myClass<std::string>* p) {
stringVec.push_back(p);
}
template<typename T>
struct myClass
{
myClass()
{
add(this);
}
T value;
};

Accessing functions of a derived crtp class from the base calls

I need to be able to access a static method of the derived class, from within a base CRTP class. Is there a way in which I can achieve this?
Here is example code:
#define REQUIRES(...) std::enable_if_t<(__VA_ARGS__), bool> = true
template<typename Derived>
struct ExpressionBase {
Derived& derived() { return static_cast<Derived&>(*this); }
const Derived& derived() const { return static_cast<const Derived&>(*this); }
constexpr static int size()
{
return Derived::size();
}
template<typename T, REQUIRES(size() == 1)>
operator T() const;
};
struct Derived : public ExpressionBase<Derived>
{
constexpr static int size()
{
return 1;
}
};
Deriving from ExpressionBase<Derived> involves the instantiation of ExpressionBase<Derived>, therefore involves the declaration of the entity
template<typename T, REQUIRES(size() == 1)>
operator T() const;
Here, std::enable_if_t got a template argument that is ill-formed (because Derived isn't complete yet). The SFINAE rule does not apply here, because the ill-formed expression is not in direct context of template argument type, thus it is treated as a hard error.
In order to make the ill-formation happen at an immediate context, use the following code:
#include <type_traits>
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <class T>
struct type_wrapper {
using type = T;
};
#define REQUIRES(...) std::enable_if_t<(__VA_ARGS__), bool> = true
template<typename Derived>
struct ExpressionBase {
Derived& derived() { return static_cast<Derived&>(*this); }
const Derived& derived() const { return static_cast<const Derived&>(*this); }
struct MyCond {
static constexpr bool value = Derived::size() == 1;
};
template<typename T, typename = typename lazy_enable_if<MyCond, type_wrapper<T>>::type>
operator T () const {
return T{};
}
};
struct Derived : public ExpressionBase<Derived>
{
constexpr static int size() {
return 1;
}
};
int main() {
Derived d;
int i = d;
return 0;
}
It is actually adapted from boost, which you can find more details here.

Dynamic casting work both shared and weak pointers inside of template member function without code duplication

I have my Find method which I want to use both with shared and weak pointers. Live example
using namespace std;
template<typename value>
struct A
{
template < typename T, typename F >
T Find( F filterFunction)
{
for ( size_t i = 0; i < iteratableList.size(); i++)
{
auto castedTerrain = dynamic_pointer_cast<typename T::element_type>(iteratableList[i]);
if ( castedTerrain && filterFunction(castedTerrain) )
return iteratableList[i];
}
return T();
}
std::vector<value> iteratableList;
};
int main()
{
{
std::vector<std::shared_ptr<std::string>> names = { make_shared<std::string>("needle"), make_shared<std::string>("manyOtherNames") } ;
A<std::shared_ptr<std::string>> iterateable{ names };
iterateable.Find<std::shared_ptr<std::string>>([] ( std::shared_ptr<std::string> in ){ return *in == "needle";});
}
// When I use weak pointer my Find function fails.
//{
// std::vector<std::shared_ptr<std::string>> weakNames ;
// for ( auto elem : names )
// weakNames.push_back(elem)
// A<std::weak_ptr<std::string>> iterateable{ weakNames };
// iterateable.Find<std::weak_ptr<std::string>>([] ( std::weak_ptr<std::string> in ){ return *in == "needle";});
//}
}
I know I can do something like
std::is_same< std::weak_ptr ... > and use std::true_type and std::false_type but I am curious if there is a better and cleaner way to achieve avoid code duplication just for .lock() method.
Just have a template function you can use to obtain the "real" pointer. The specialization for std::shared_ptr just returns the argument:
template <typename T>
struct resolve_pointer;
template <typename T>
struct resolve_pointer<std::shared_ptr<T>>
{
static std::shared_ptr<T> resolve(std::shared_ptr<T> & p) const {
return p;
}
};
template <typename T>
struct resolve_pointer<std::weak_ptr<T>>
{
static std::shared_ptr<T> resolve(std::weak_ptr<T> & p) const {
return p.lock();
}
};
Now your Find function, in place of iteratableList[i], use resolve_pointer<T>::resolve(iteratableList[i]).
I'm a potato, an overloaded free function would work just as well and be a bit simpler to understand:
template <typename T>
std::shared_ptr<T> resolve_pointer(std::shared_ptr<T> & p) {
return p;
}
template <typename T>
std::shared_ptr<T> resolve_pointer(std::weak_ptr<T> & p) {
return p.lock();
}
If your goal is to be able to extend your code to provide interoperability with any strong/weak pointer pairs that have an implemented dynamic cast operation (shown here the std::strong/weak_ptr and boost::strong/weak_ptr), you can do this using a set of traits, like so... beware, dragons ahead:
// Defines a resolve static function to get a strong pointer from either
// a strong or a weak pointer.
template <typename T>
struct smart_pointer_info;
template <typename T>
struct smart_pointer_info<std::shared_ptr<T>>
{
typedef std::shared_ptr<T> ptr_type;
typedef T element_type;
typedef std::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p;
}
};
template <typename T>
struct smart_pointer_info<std::weak_ptr<T>>
{
typedef std::weak_ptr<T> ptr_type;
typedef T element_type;
typedef std::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p.lock();
}
};
template <typename T>
struct smart_pointer_info<boost::shared_ptr<T>>
{
typedef boost::shared_ptr<T> ptr_type;
typedef T element_type;
typedef boost::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p;
}
};
template <typename T>
struct smart_pointer_info<boost::weak_ptr<T>>
{
typedef boost::weak_ptr<T> ptr_type;
typedef T element_type;
typedef boost::shared_ptr<T> resolved_type;
static resolved_type resolve(ptr_type & p) {
return p.lock();
}
};
// Provides a static "cast" function that converts a strong pointer T
// into a strong point that points at an object of type D.
template <typename T, typename D>
struct smart_pointer_dynamic_cast;
template <typename T, typename D>
struct smart_pointer_dynamic_cast<std::shared_ptr<T>, D>
{
typedef std::shared_ptr<T> ptr_type;
typedef std::shared_ptr<D> cast_type;
static cast_type cast(ptr_type & p) {
return std::dynamic_pointer_cast<D>(p);
}
};
template <typename T, typename D>
struct smart_pointer_dynamic_cast<boost::shared_ptr<T>, D>
{
typedef boost::shared_ptr<T> ptr_type;
typedef boost::shared_ptr<D> cast_type;
static cast_type cast(ptr_type & p) {
return boost::dynamic_pointer_cast<D>(p);
}
};
// Helper so we can omit the template parameter for the source pointer type.
template <typename D>
struct dynamic_cast_helper
{
template <typename P>
static typename smart_pointer_dynamic_cast<typename smart_pointer_info<P>::resolved_type, D>::cast_type cast(P & p) {
typename smart_pointer_info<P>::resolved_type r = smart_pointer_info<P>::resolve(p);
return smart_pointer_dynamic_cast<typename smart_pointer_info<P>::resolved_type, D>::cast(r);
}
};
// Then we might use it like so:
class A {
public:
virtual void print() {
std::cout << "A::print()" << std::endl;
}
};
class B : public A {
public:
virtual void print() {
std::cout << "B::print()" << std::endl;
}
};
int main()
{
auto x = std::make_shared<B>();
std::weak_ptr<B> xw{x};
auto y = boost::make_shared<B>();
boost::weak_ptr<B> yw{y};
dynamic_cast_helper<A>::cast(x)->print();
dynamic_cast_helper<A>::cast(xw)->print();
dynamic_cast_helper<A>::cast(y)->print();
dynamic_cast_helper<A>::cast(yw)->print();
return 0;
}
(Demo)
Your cast dynamic_pointer_cast<typename T::element_type>(iteratableList[i]) then becomes dynamic_cast_helper<typename smart_pointer_info<T>::element_type>::cast(iteratableList[i]) and all the types along the way get inferred by the compiler.

template specialization for constructor of a parent class

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
}

boost concept check operator() overload

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;
}