How can I use and specialize a 'curious repeating template pattern' - c++

I would like to pass in some parameters into a curious repeating template pattern. I would then like this base class to create other objects and pass both types into the subclass. This would allow me to generalize the base class to perform some common logic before the subclass is called. Each subclass should be able to be a specialized instance of the one level hierarchy.

Here is how to do this:
struct ParamOne {
double val {0.0};
};
struct ParamTwo {
int val {0};
};
template<typename P, typename Data, typename Other>
class Baseclass
{
public:
using subclass_type = P;
using data_type = Data;
using other_type = Other;
bool Method( const Data &data);
};
template<typename P, typename Data, typename Other> using pdata_type = typename P::data_type;
template<typename P, typename Data, typename Other> using pother_type = typename P::other_type;
template<typename P, typename Data, typename Other>
bool Baseclass<P, Data, Other>::Method( const Data &data )
{
P& Subclass = static_cast<P&>( *this );
pother_type<P, Data, Other> other;
other.val = 11;
return Subclass.SubclassMethod( data, other );
}
template<typename Data, typename Other>
class Subclass : public Baseclass<Subclass<Data, Other>, Data, Other>
{
public:
using data_type = Data;
using other_type = Other;
bool SubclassMethod( const Data &data, Other &other );
};
template<typename Data, typename Other>
bool Subclass<Data, Other>::SubclassMethod( const Data &data, Other &other )
{
return true;
}
template<>
bool Subclass<ParamOne, ParamTwo>::SubclassMethod( const ParamOne &data, ParamTwo &other )
{
return true;
}
int main(int argc, char **argv)
{
ParamOne one;
one.val = 5.0;
Subclass<ParamOne, ParamTwo> test;
test.Method(one);
return 0;
}

Related

Store member get/set functions for later use

I want to store a pair of member get/set functions for later use with an object of type T.
I have a partially working setup, see below. Questions remain however:
How do I (smartly) deal with all possible variants? member_get could be [returning value or const value& or even value& | const or non-const] member_set could be [accepting const &, & or &&]. Sure, 'best practices' would rule out some combinations, but I cannot rely on that as the definition of member_get and member_set is out of my hands.
How do I correctly deal with possible member_set move semantics?
Is there a different/better/simpler general way to approach this?
Notes:
I intentionally left open the exact type S of the setter. Not sure if that's a good or bad idea.
Lambdas obviously come to mind, but I can't see how they can help the issue. The caller of Make( get, set ) is not supposed to supply lambdas. That would be just delegating the problem to him!?
any std::function ideas should be ruled out because of the overhead
template <typename T, typename V, typename G, typename S>
class GetSet
{
public:
constexpr GetSet( G member_get, S member_set ) : Get( member_get ), Set( member_set )
{ }
auto GetValue( const T& t ) const
{
return ( t.*Get )( );
}
void SetValue( T& t, V&& value ) const
{
( t.*Set )( std::forward<V>( value ) );
}
private:
G Get;
S Set;
};
template <typename T, typename ValueType, typename S>
constexpr auto Make( ValueType( T::*member_get )( ) const, S member_set )
{
using G = ValueType( T::* )( ) const;
return GetSet<T, ValueType, G, S>( member_get, member_set );
}
Not sure why you need this, but the simplest solution is below.
#include <utility>
template <class F> struct ClassType;
template <typename Ret, typename TCls, typename... Args>
struct ClassType<Ret (TCls::*)(Args...)> {
using type = TCls;
};
template <typename Ret, typename TCls>
struct ClassType<Ret (TCls::*)() const> {
using type = TCls;
};
template<class TFnGet, class TFnSet>
class GetSet
{
public:
using TGet = TFnGet;
using TSet = TFnSet;
public:
inline GetSet(TGet fnGet, TSet fnSet)
: m_fnGet(fnGet), m_fnSet(fnSet)
{
}
template<class T>
inline decltype(auto) GetValue(T&& r) const
{
static_assert(std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type, typename ClassType<TFnGet>::type>::value, "wrong type of r?");
return (r.*m_fnGet)();
}
template<class T, class TValue>
inline void SetValue(T&& r, TValue&& value)
{
static_assert(std::is_same<typename std::remove_cv<typename std::remove_reference<T>::type>::type, typename ClassType<TFnSet>::type>::value, "wrong type of r?");
(r.*m_fnSet)(std::forward<TValue>(value));
}
private:
TGet m_fnGet;
TSet m_fnSet;
};
template<class TGet, class TSet>
GetSet<TGet, TSet> MakeGetSet(TGet fnGet, TSet fnSet)
{
static_assert(std::is_same<typename ClassType<TGet>::type, typename ClassType<TSet>::type>::value, "members of different classes?");
return GetSet<TGet, TSet>(fnGet, fnSet);
}
verified with:
class A
{
public:
void Set(int i) {}
int Get() const { return 0;}
void SetRef(char& ch) {}
A& GetRef() { return *this;}
void SetRRef(float&& ) {}
int&& GetRRef() { return 1; }
void SetConstRef(const char& ch) {}
int GetNotConst() { return 0;}
};
int main(int argc, char* argv[])
{
A a;
auto gs = MakeGetSet(&A::Get, &A::Set);
auto gsRef = MakeGetSet(&A::GetRef, &A::SetRef);
auto gs2 = MakeGetSet(&A::GetRRef, &A::SetRRef);
auto gsNonConst = MakeGetSet(&A::GetNotConst, &A::SetConstRef);
int x = gs.GetValue(a);
gs.SetValue(a, 2);
const A& ra = a;
x = gs.GetValue(ra);
A& r = gsRef.GetValue(a);
char ch =' ';
gsRef.SetValue(a, ch);
x = gs2.GetValue(a);
gs2.SetValue(a, 1.1f);
x = gsNonConst.GetValue(a);
gsNonConst.SetValue(a, ch);
std::cout << "ok\n";
return 0;
}

Conditionally Remove Variable Based on Template Type

Currently I am using code that looks like the below.
template<class T, class U = char>
struct ScoredObject {
ScoredObject( T *object, double score, const U &data = U() ) noexcept( noexcept( U( data ) ) ) : object( object ), score( score ), data( data ) {}
T *object;
double score;
U data;
// ...
};
In all cases, except 1, the data variable is not used. It's default is char to just waste as little space as possible. Realistically, I'd like it to be void, but of course then it won't compile.
I know I can do some std::enable_ifs on the constructor, but the issue is still with the data variable. Is it possible to use some sort of template "magic" to remove the data variable when U is void?
Basically, I want to do something like this (which I know isn't valid)
template<typename f = U, typename std::enable_if<!std::is_void<f>::value, bool>::type = true>
U data;
You can inherit Scored_object from different bases depending on the type of U. Something like this:
template<class T, class U>
struct Scored_object_base : Scored_object_base<T, void> {
U data;
using Base = Scored_object_base<T, void>;
Scored_object_base(T* object, double score, const U& data)
: Base(object, score), data(data) {}
};
template<class T>
struct Scored_object_base<T, void> {
T* object;
double score;
Scored_object_base(T* object, double score)
: object(object), score(score) {}
};
template<class T, class U = void>
struct Scored_object : Scored_object_base<T, U> {
using Base = Scored_object_base<T, U>;
using Base::Base;
};
template<class T, class U>
bool operator==(const Scored_object<T, U>& o1, const Scored_object<T, U>& o2) {
const auto f = (*o1.object == *o2.object && o1.score == o2.score);
if constexpr (std::is_void_v<U>)
return f;
else
return f && o1.data == o2.data;
}
int main() {
int i;
Scored_object<int, void> o1(&i, 1);
Scored_object<int, char> o2(&i, 1, 'a');
std::cout << sizeof(o1) << std::endl; // Output: 16
std::cout << sizeof(o2) << std::endl; // Output: 24
}

Hold multiple maps having different value types in a class and support type based lookup

I want to implement a heterogeneous storage, using multiple maps having different value type. I am indexing the maps based on the value types. For that I am using typelist. This is a simplified example.
My type-list class looks like following.
namespace details
{
struct null{};
template<int N, typename E, typename T, typename ... Ts>
struct index : index<N+1, E, Ts...> {};
template<int N, typename E, typename ... Ts>
struct index<N, E, E, Ts...>
{
constexpr static int value = N;
};
template<int N, typename E>
struct index<N, E, null>
{
constexpr static int value = -1;
};
}
template<typename ... Ts>
struct typelist
{
using type = typelist<Ts...>;
template<typename T>
struct index : details::index<0, T, Ts..., details::null> {};
};
And storage class implementation following, A template class holding values of type T.
#include <iostream>
#include <tuple>
#include <typeinfo>
#include <map>
template<typename T>
struct storage_impl
{
//storage_impl(storage_impl const &) = delete;
bool try_getting(int key, T &value)
{
auto search = _storage.find(key);
if(search != _storage.end() )
{
value = search->second;
return true;
}
return false;
}
std::map<int,T> _storage;
};
And finally the storage manager looks like, it has several storage_impl instance, and I want to index on them based on type.
struct storage_manager{
// tuple storing different storage_impls
std::tuple< storage_impl<double> , storage_impl<std::string> > storages { storage_impl<double>{},storage_impl<std::string>{} };
using item_types = typelist<double,std::string>;
storage_manager(){}
~storage_manager(){}
storage_manager(storage_manager const &) = delete;
template<typename T>
bool try_getting(int key, T &value)
{
return std::get<item_types::index<T>::value>(storages).try_getting(key,value);
}
};
int main()
{
storage_manager mgr;
double val1;
std::cout<<mgr.try_getting(123,val1);
}
Every thing works till the storage_impl is copyable. But I want storage_impl to be non-copyable.
How to achieve same with my storage_impl being non-copyable.
P.S. - Did not want to use inheritance for same.
Following is my working code, I have declared cache_impls as member variables and specialized function storage_ref for every case.
I have implemented only try_get, other functions can be implemented using storage_ref.
#include <iostream>
#include <tuple>
#include <map>
#include <boost/noncopyable.hpp>
template<typename T>
struct storage_impl : public boost::noncopyable
{
storage_impl(){}
~storage_impl(){}
bool try_getting(int key, T &value)
{
auto search = _storage.find(key);
if(search != _storage.end() )
{
value = search->second;
return true;
}
return false;
}
bool try_setting(int key, T const &value)
{
auto search = _storage.insert(std::make_pair(key,value));
if(search.second == true )
{
return true;
}
return false;
}
bool exists(int key)
{
auto search = _storage.find(key);
if(search != _storage.end() )
{
return true;
}
return false;
}
std::map<int,T> _storage;
};
struct storage_manager : public boost::noncopyable
{
storage_impl<double> double_store;
storage_impl<std::string> string_store;
template<typename T>
struct item_return{ using type = storage_impl<T>; };
template<typename T>
typename item_return<T>::type storage_ref();
template<typename T>
bool try_getting(int key, T &value)
{
return storage_ref<T>().try_getting(key,value);
}
template<typename T>
bool try_setting(int key, T const &value)
{
return storage_ref<T>().try_setting(key,value);
}
template<typename T>
bool exists(int key)
{
return storage_ref<T>().exists(key);
}
storage_manager(){}
~storage_manager(){}
};
//double specialization
template<>
struct storage_manager::item_return<double>{ using type = storage_impl<double>&; };
template<>
inline storage_impl<double>& storage_manager::storage_ref<double>()
{
return double_store;
}
//std::string specialization
template<>
struct storage_manager::item_return<std::string>{ using type = storage_impl<std::string>&; };
template<>
inline storage_impl<std::string>& storage_manager::storage_ref<std::string>()
{
return string_store;
}
int main()
{
storage_manager mgr;
double val1 = 90;
std::cout<<mgr.try_getting(123,val1)<<'\n';
std::cout<<mgr.try_setting(123,val1)<<'\n';
std::cout<<mgr.exists<double>(123)<<'\n';
std::string val2;
std::cout<<mgr.try_getting(123,val2)<<'\n';
}
Looking forward for alternatives...

Select C++ template specialization based on member type availability

I am writing a sort of serialization class. It must provide functions for containers. Current implementation is:
template <typename InsertIter>
bool readContainer(InsertIter result)
{
typedef typename InsertIter::container_type::value_type tVal;
UInt32 size = 0;
if (!read(size))
return false;
for (UInt32 i = 0; i < size; ++i)
{
tVal val;
if (!read(val))
return false;
*result++ = val;
}
return true;
}
template <typename InsertIter>
bool readMap(InsertIter result)
{
typedef typename InsertIter::container_type::key_type tKey;
typedef typename InsertIter::container_type::mapped_type tVal;
UInt32 size = 0;
if (!read(size))
return false;
for (UInt32 i = 0; i < size; ++i)
{
std::pair<tKey, tVal> pair;
if (!read(pair))
return false;
*result++ = pair;
}
return true;
}
As you can see, I must to create different implementations for map-like types (std::map) and other containers, because std::map::value_type is std::pair(const K, V) and not std::pair(K, V).
So, I want to create method read(InsertIter) which will automatically select appropriate readContainer(InsertIter) or readMap(InsertIter). Is this possible?
I have an example that does something very similar, and it should be very simple for you to convert to something that you need :
#include <iostream>
template< typename T >
struct A;
template<>
struct A< int >
{
void foo() const
{
std::cout<<"A(int)::foo()"<<std::endl;
}
};
template<>
struct A< float >
{
void foo() const
{
std::cout<<"A(float)::foo()"<<std::endl;
}
};
template< typename T >
void call( const A<T> &a)
{
a.foo();
}
struct B
{
template<typename T>
void bar(const A<T> &a)
{
call(a);
}
};
int main()
{
A<int> a1;
A<float> a2;
B b;
b.bar(a1);
b.bar(a2);
}
You need to give proper names, and replace int and float in the above example with appropriate container types, and implement needed functionality.
I have successfully solved my problem.
Thanks to Johan Lundberg and especially to n.m. - I was not familiar with SFINAE idiom and your links and samples helped me a lot.
I was not able to use C++11 features (project specifics), but they are not needed.
Current code looks like this:
struct SFINAE
{
typedef char __one;
typedef struct { char __arr[2]; } __two;
};
template <typename T>
class has_mapped_type : public SFINAE
{
template <typename C> static __one test(typename C::mapped_type *);
template <typename C> static __two test(...);
public:
enum { value = (sizeof(test<T>(0)) == sizeof(__one)) };
};
class Serializer
{
template <typename InsertIter>
bool read(InsertIter result) const
{
return readContainerSelector< InsertIter,
has_mapped_type<typename InsertIter::container_type>::value
> ::read(result, *this);
}
template <typename InsertIter, bool isMapType>
struct readContainerSelector;
template <typename InsertIter>
struct readContainerSelector<InsertIter, true>
{
static bool read(InsertIter result, Serializer const& ser)
{
return ser.readMap(result);
}
};
template <typename InsertIter>
struct readContainerSelector<InsertIter, false>
{
static bool read(InsertIter result, Serializer const& ser)
{
return ser.readContainer(result);
}
};
// methods from my topic post
template <typename InsertIter> bool readContainer(InsertIter result);
template <typename InsertIter> bool readMap(InsertIter result)
};

Deduce return type of operator/function for templates

Is something like this possible?
// We can even assume T and U are native C++ types
template<typename T, typename U>
magically_deduce_return_type_of(T * U) my_mul() { return T * U; }
Or would somebody have to hack up a return_type struct and specialize it for every pair of native types?
Heard of decltype?
In C++0x you can do
template<class T, class U>
auto mul(T x, U y) -> decltype(x*y)
{
return x*y;
}
You can do this in non C++0x code:
template<typename T, typename U> class Mul
{
T t_;
U u_;
public:
Mul(const T& t, const U& u): t_(t), u_(u) {}
template <class R>
operator R ()
{
return t_ * u_;
}
};
template<typename T, typename U>
Mul<T, U> mul(const T& t, const U& u)
{
return Mul<T, U>(t, u);
}
Usage:
char t = 3;
short u = 4;
int r = mul(t, u);
Here we have two type deductions. We implicitly declare return type by usage, not exactly decltype(T*U)
I'm using Visual Studio 2008, so I had to come up with a non C++0x way. I ended up doing something like this.
template<typename T> struct type_precedence { static const int value = -1; };
template< > struct type_precedence<long double> { static const int value = 0; };
template< > struct type_precedence<double> { static const int value = 1; };
template< > struct type_precedence<float> { static const int value = 2; };
template< > struct type_precedence<unsigned long long> { static const int value = 3; };
template< > struct type_precedence<long long> { static const int value = 4; };
template< > struct type_precedence<unsigned long> { static const int value = 5; };
template< > struct type_precedence<long> { static const int value = 6; };
template< > struct type_precedence<unsigned int> { static const int value = 7; };
template< > struct type_precedence<int> { static const int value = 8; };
template< > struct type_precedence<unsigned short> { static const int value = 9; };
template< > struct type_precedence<short> { static const int value = 10; };
template< > struct type_precedence<unsigned char> { static const int value = 11; };
template< > struct type_precedence<char> { static const int value = 12; };
template< > struct type_precedence<bool> { static const int value = 13; };
/////////////////////////////////////////////////////////////////////////////////////////
template<typename T, typename U, bool t_precedent = ((type_precedence<T>::value) <= (type_precedence<U>::value))>
struct precedent_type {
typedef T t;
};
template<typename T, typename U>
struct precedent_type<T,U,false> {
typedef U t;
};
/////////////////////////////////////////////////////////////////////////////////////////
template<typename T, typename U>
typename precedent_type<T,U>::t my_mul() { return T * U; }
EDIT: Here's the example - I'm actually doing this to multiply vectors. It looks something like this:
template<int N, typename T, typename U>
vec<N,typename precedent_type<T,U>::t> operator *(const vec<N,T>& v1,const vec<N,U>& v2) {
...
}
...
double3 = float3 * double3;
float4 = float4 * int4;
etc.
http://www2.research.att.com/~bs/C++0xFAQ.html#decltype
pre-C++0x
I don't know exactly what you want to accomplish, so:
template<typename T, typename U>
void my_mul(T t, U u, bool& overflow)
{
my_mul_impl(t*u, overflow);
}
template<typename TmultU>
void my_mul_impl(TmultU mult, bool& overflow)
{
//here you know the type and can do something meta-weird :)
if(mult > type_traits<TmultU>::max_allowed_in_my_cool_program())
overflow = true;
}
There is more