Lets say I'm writing a some kind of conversion operator, and I want to use it like that:
SomeType a;
AnotherType b = conv<AnotherType>(a);
First, I write the base (default) function:
template <typename T, typename U>
inline T conv(const U& a)
{
return T(a);
}
Full specialization (or a non-template overload) is not a problem, however, when I want to do something like that:
template <typename T>
inline Point<T> conv(const Ipoint& p)
{
return Point<T>(p.x, p.y);
}
I can't write any more conversion functions from the Ipoint (to the FunkyPoint< T > for example) due to ambiguity, and I end up with an awkward usage:
Ipoint a;
Point<double> b = conv<double>(a); //ugly!
//Point<double> b = conv<Point<double> >(a); //I want that, but it (obviously) does not compile.
Is there any way of doing it nicely?
Implement the body in a class template and then you can partially specialize:
template < typename T, typename U >
struct convert
{
static T apply(U const& u) { return T(u); }
};
template < typename T, typename U >
T conv(U const& u) { return convert<T,U>::apply(u); }
template < typename T >
struct convert<Point<T>, Ipoint>
{
static Point apply(Ipoint const& u)
{
return Point(u.x, u.y);
}
};
Should work but is untested.
Related
I'm struggling with some template programming and I hope you can give me some help. I coded a C++11 interface that, given some structs like:
struct Inner{
double a;
};
struct Outer{
double x, y, z, r;
Inner in;
};
Implements a getter/setter to the real data that is customized to the specified struct members:
MyData<Outer, double, &Outer::x,
&Outer::y,
&Outer::z,
&Outer::in::a //This one is not working
> state();
Outer foo = state.get();
//...
state.set(foo);
I managed to implement this for simple structs in the following way:
template <typename T, typename U, U T::* ... Ms>
class MyData{
std::vector<U *> var;
public:
explicit MyData();
void set(T const& var_);
T get() const;
};
template <typename T, typename U, U T::* ... Ms>
MyData<T, U, Ms ... >::Struct():var(sizeof...(Ms))
{
}
template <typename T, typename U, U T::* ... Ms>
void MyData<T, U, Ms ...>::set(T const& var_){
unsigned i = 0;
for ( auto&& d : {Ms ...} ){
*var[i++] = var_.*d;
}
}
template <typename T, typename U, U T::* ... Ms>
T MyData<T, U, Ms ...>::get() const{
T var_;
unsigned i = 0;
for ( auto&& d : {Ms ...} ){
var_.*d = *var[i++];
}
return var_;
}
But it fails when I pass a member of a nested struct. Ideally, I'd like to implement a generic pointer to member type that allows me to be compatible with several levels of scope resolutions. I found this approach, but I'm not sure if this should be applied to my problem or if there exists some implementation ready to use. Thanks in advance!
Related posts:
Implicit template parameters
Pointer to inner struct
You might wrap member pointer into struct to allow easier chaining:
template <typename...> struct Accessor;
template <typename T, typename C, T (C::*m)>
struct Accessor<std::integral_constant<T (C::*), m>>
{
const T& get(const C& c) { return c.*m; }
T& get(C& c) { return c.*m; }
};
template <typename T, typename C, T (C::*m), typename ...Ts>
struct Accessor<std::integral_constant<T (C::*), m>, Ts...>
{
auto get(const C& c) -> decltype(Accessor<Ts...>().get(c.*m))
{ return Accessor<Ts...>().get(c.*m); }
auto get(C& c) -> decltype(Accessor<Ts...>().get(c.*m))
{ return Accessor<Ts...>().get(c.*m); }
};
template <typename T, typename U, typename ...Ts>
class MyData
{
std::vector<U> vars{sizeof...(Ts)};
template <std::size_t ... Is>
T get(std::index_sequence<Is...>) const
{
T res;
((Ts{}.get(res) = vars[Is]), ...); // Fold expression C++17
return res;
}
template <std::size_t ... Is>
void set(std::index_sequence<Is...>, T const& t)
{
((vars[Is] = Ts{}.get(t)), ...); // Fold expression C++17
}
public:
MyData() = default;
T get() const { return get(std::index_sequence_for<Ts...>()); }
void set(const T& t) { return set(std::index_sequence_for<Ts...>(), t); }
};
With usage similar to
template <auto ...ms> // C++17 too
using Member = Accessor<std::integral_constant<decltype(ms), ms>...>;
MyData<Outer, double, Member<&Outer::x>,
Member<&Outer::y>,
Member<&Outer::z>,
Member<&Outer::in, &Inner::a>
> state;
std::index_sequence is C++14 but can be implemented in C++11.
Folding expression from C++17 can be simulated too in C++11.
typename <auto> (C++17) should be replaced by typename <typename T, T value>.
Demo
A generalization of a member pointer is a function that can map T to X& at compile time.
In c++17 it isn't hard to wire things up thanks to auto. In c++11 it gets harder. But the basic idea is that you don't actually pass member pointers, you pass types, and those types know how to take your class and get a reference out of them.
template<class T, class D, class...Fs>
struct MyData {
std::array<D*, sizeof...(Fs)> var = {};
explicit MyData()=default;
void set(T const& var_) {
var = {{ Fs{}(std::addressof(var_))... }};
}
T get() {
T var_;
std::size_t index = 0;
using discard=int[];
(void)discard{ 0, (void(
*Fs{}(std::addressof(var_)) = *var[index++]
),0)... };
return var_;
}
};
it remains to write a utility that makes writing the Fs... easy for the member pointer case
template<class X, X M>
struct get_ptr_to_member_t;
template<class T, class D, D T::* M>
struct get_ptr_to_member_t< D T::*, M > {
D const* operator()( T const* t )const{
return std::addressof( t->*M );
}
};
#define TYPE_N_VAL(...) \
decltype(__VA_ARGS__), __VA_ARGS__
#define MEM_PTR(...) get_ptr_to_member_t< TYPE_N_VAL(__VA_ARGS__) >
now the basic case is
MyData< Outer, double, MEM_PTR(&Outer::x), MEM_PTR(&Outer::y) >
The more complex case can now be handled.
An approach would be to teach get_ptr_to_member to compose. This is annoying work, but nothing fundamental. Arrange is so that decltype(ptr_to_member_t * ptr_to_member_t) returns a type that instances right, applies it, then takes that pointer and runs the left hand side on it.
template<class First, class Second>
struct composed;
template<class D>
struct composes {};
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
template<class First, class Second>
struct composed:composes<composed<First, Second>> {
template<class In>
auto operator()(In&& in) const
RETURNS( Second{}( First{}( std::forward<In>(in) ) ) )
};
template<class First, class Second>
composed<First, Second> operator*( composes<Second> const&, composes<First> const& ) {
return {};
}
then we upgrade:
template<class X, X M>
struct get_ptr_to_member_t;
template<class T, class D, D T::* M>
struct get_ptr_to_member_t< D T::*, M >:
composes<get_ptr_to_member_t< D T::*, M >>
{
D const* operator()( T const* t )const{
return std::addressof( t->*M );
}
};
and now * composes them.
MyData<TestStruct, double, MEM_PTR(&Outer::x),
MEM_PTR(&Outer::y),
MEM_PTR(&Outer::z),
decltype(MEM_PTR(&Inner::a){} * MEM_PTR(&Outer::in){})
> state();
answre probably contains many typos, but design is sound.
In c++17 most of the garbage evaporates, like the macros.
I would use lambda approach to implement similar functionalities in C++17(C++14 is also ok, just change the fold expression):
auto access_by() {
return [] (auto &&t) -> decltype(auto) {
return decltype(t)(t);
};
}
template<class Ptr0, class... Ptrs>
auto access_by(Ptr0 ptr0, Ptrs... ptrs) {
return [=] (auto &&t) -> decltype(auto) {
return access_by(ptrs...)(decltype(t)(t).*ptr0);
};
}
auto data_assigner_from = [] (auto... accessors) {
return [=] (auto... data) {
return [accessors..., data...] (auto &&t) {
((accessors(decltype(t)(t)) = data), ...);
};
};
};
Let's see how to use these lambdas:
struct A {
int x, y;
};
struct B {
A a;
int z;
};
access_by function can be used like:
auto bax_accessor = access_by(&B::a, &A::x);
auto bz_accessor = access_by(&B::z);
Then for B b;, bax_accessor(b) is b.a.x; bz_accessor(b) is b.z. Value category is also preserved, so you can assign: bax_accessor(b) = 4.
data_assigner_from() will construct an assigner to assign a B instance with given accessors:
auto data_assigner = data_assigner_from(
access_by(&B::a, &A::x),
access_by(&B::z)
);
data_assigner(12, 3)(b);
assert(b.z == 3 && b.a.x == 12);
In my C++ code I have a Matrix class, and some operators written to multiply them. My class is templated which mean I can have int, float, double ... matrices.
My operator overload is classic I guess
template <typename T, typename U>
Matrix<T>& operator*(const Matrix<T>& a, const Matrix<U>& b)
{
assert(a.rows() == b.cols() && "You have to multiply a MxN matrix with a NxP one to get a MxP matrix\n");
Matrix<T> *c = new Matrix<T>(a.rows(), b.cols());
for (int ci=0 ; ci<c->rows() ; ++ci)
{
for (int cj=0 ; cj<c->cols() ; ++cj)
{
c->at(ci,cj)=0;
for (int k=0 ; k<a.cols() ; ++k)
{
c->at(ci,cj) += (T)(a.at(ci,k)*b.at(k,cj));
}
}
}
return *c;
}
In this code I return a matrix of the same type than the first parameter i.e. Matrix<int> * Matrix<float> = Matrix<int>. My question is how can I detect the most precised type among the two I give to not lose too much precision i.e. to have Matrix<int> * Matrix<float> = Matrix<float> ? Is there a clever to do it ?
What you want is just the type that happens when you multiply a T by a U. That can be given by:
template <class T, class U>
using product_type = decltype(std::declval<T>() * std::declval<U>());
You can just use that as an extra defaulted template parameter:
template <typename T, typename U, typename R = product_type<T, U>>
Matrix<R> operator*(const Matrix<T>& a, const Matrix<U>& b) {
...
}
In C++03 you can accomplish the same thing by doing a giant series of overloads with lots of small helper types like so (this is how Boost does it):
template <int I> struct arith;
template <int I, typename T> struct arith_helper {
typedef T type;
typedef char (&result_type)[I];
};
template <> struct arith<1> : arith_helper<1, bool> { };
template <> struct arith<2> : arith_helper<2, bool> { };
template <> struct arith<3> : arith_helper<3, signed char> { };
template <> struct arith<4> : arith_helper<4, short> { };
// ... lots more
We then can write:
template <class T, class U>
class common_type {
private:
static arith<1>::result_type select(arith<1>::type );
static arith<2>::result_type select(arith<2>::type );
static arith<3>::result_type select(arith<3>::type );
// ...
static bool cond();
public:
typedef typename arith<sizeof(select(cond() ? T() : U() ))>::type type;
};
Assuming you write out all the integer types, then you can use typename common_type<T, U>::type where before I used product_type.
If this isn't a demonstration of how cool C++11 is, I don't know what is.
Note, operator* should not return a reference. What you're doing will leak memory.
Consider the code below of a unary functor which has been simplified
#include <type_traits>
template <class FuncT, class FuncArgT>
class UnaryFunctor
{
FuncT func;
public:
UnaryFunctor(FuncT const& func) : func(func) {}
template <class ArgsT> struct result {};
template <class F, class ArgT>
struct result < F(ArgT) >
{
typedef typename std::result_of<FuncT(ArgT)>::type type;
};
template <class ArgT>
typename result<UnaryFunctor(ArgT)>::type
inline operator()(ArgT const& arg) const
{
return func(arg);
}
};
template <class FuncT, class ArgT>
struct Result
{
typedef typename std::result_of<UnaryFunctor<FuncT, ArgT>(ArgT)>::type type;
};
template <class FuncT, class ArgT>
typename Result<FuncT, ArgT>::type
inline unary_apply(FuncT const& func, ArgT const& arg)
{
return UnaryFunctor<FuncT, ArgT>(func)(arg);
}
So essentially the purpose is calling a function with a value that is being passed.
Lets say we have the two simple functions below.
template <class T> T addValueTemplate(T const& val) { return val + 3; }
unsigned int addValue2(unsigned int const& val) { return val + 3; }
Calling this is fine
unsigned int i = 1, j;
j = unary_apply(&addValue2, i);
But I cant work out how to do the same thing but for the template class addValueTemplate. For example this wont compile
j = unary_apply(&addValueTemplate<unsigned int>, i);
Is there a way to do that ?
This compiles fine in GCC by the way but not in msvc
Looks like a bug in MSVC. It thinks &addValueTemplate<unsigned int> is a function, not a function pointer. Use an intermediate function pointer variable:
unsigned int (*av)(unsigned int const&) = &addValueTemplate;
j = unary_apply(av, i);
Or use this to fool MSVC:
template <typename T>
T* identity(T* x) { return x; }
j = unary_apply(identity(&addValueTemplate<unsigned int>),i);
(for completeness, overload identity for const/non-const/rvalue references/pointers)
I have created a matrix class and want to add two matrices of different data types. Like for int and double return type of matrice should be double. How can I do that???
This is my code
template<class X>
class Matrix
{
..........
........
template<class U>
Matrix<something> operator+(Matrix<U> &B)
{
if((typeid(a).before(typeid(B.a))))
Matrix<typeof(B.a)> res(1,1);
else
Matrix<typeof(a)> res(1,1);
}
What should be "something" here???
Also what should be done so that I can use "res" outside if else statement???
You can handle both those issues with C++11's auto return type syntax the generous assistance of #DyP :).
template<typename U>
Matrix <decltype(declval<X>()+declval<U>())> operator+(const Matrix<U> &B) const
{
Matrix< decltype( declval<X>() + declval<U>() ) > res;
// The rest...
}
With this syntax, your "something" will be the type C++ normally produces when the two template types are added.
Try common_type:
#include <type_traits>
template <typename T>
class Matrix
{
// ...
template <typename U>
Matrix<typename std::common_type<T, U>::type>
operator+(Matrix<U> const & rhs)
{
typedef typename std::common_type<T, U>::type R;
Matrix<R> m; // example
// ...
return m;
}
};
I am attempting to create a template "AutoClass" that create an arbitrary class with an arbitrary set of members, such as:
AutoClass<int,int,double,double> a;
a.set(1,1);
a.set(0,2);
a.set(3,99.7);
std::cout << "Hello world! " << a.get(0) << " " << a.get(1) << " " << a.get(3) << std::endl;
By now I have an AutoClass with a working "set" member:
class nothing {};
template < typename T1 = nothing, typename T2 = nothing, typename T3 = nothing,
typename T4 = nothing, typename T5 = nothing, typename T6 = nothing>
class AutoClass;
template <>
class AutoClass<nothing, nothing, nothing,
nothing, nothing, nothing>
{
public:
template <typename U> void set(int n,U v){}
};
template < typename T1, typename T2, typename T3,
typename T4, typename T5, typename T6>
class AutoClass: AutoClass<T2,T3,T4,T5,T6>
{
public:
T1 V;
template <typename U> void set(int n,U v)
{
if (n <= 0)
V = v;
else
AutoClass<T2,T3,T4,T5,T6>::set(n-1,v);
}
};
and I started to have problems implementing the corresponding "get". This approach doesn't compile:
template < typename T1, typename T2, typename T3,
typename T4, typename T5, typename T6>
class AutoClass: AutoClass<T2,T3,T4,T5,T6>
{
public:
T1 V;
template <typename U> void set(int n,U v)
{
if (n <= 0)
V = v;
else
AutoClass<T2,T3,T4,T5,T6>::set(n-1,v);
}
template <typename W> W get(int n)
{
if (n <= 0)
return V;
else
return AutoClass<T2,T3,T4,T5,T6>::get(n-1);
}
template <> T1 get(int n)
{
if (n <= 0)
return V;
else
return AutoClass<T2,T3,T4,T5,T6>::get(n-1);
}
};
Besides, it seems I need to implement get for the <nothing, nothing, nothing, nothing, nothing, nothing> specialization. Any Idea on how to solve this?
First of all, I prefer Boost.Fusion to Boost.Tuple as it supports a better mixin of template metaprogramming and runtime algorithms I think.
For example, I'd like to present you a little marvel:
struct Name {}; extern const Name name;
struct GivenName {}; extern const GivenName givenName;
struct Age {}; extern const Age age;
class Person
{
public:
template <class T>
struct value
{
typedef typename boost::fusion::result_of::at_key<data_type const,T>::type type;
};
template <class T>
struct has
{
typedef typename boost::fusion::result_of::has_key<data_type,T>::type type;
};
template <class T>
typename value<T>::type
get(T) { return boost::fusion::at_key<T>(mData); }
template <class T>
Person& set(T, typename value<T>::type v)
{
boost::fusion::at_key<T>(mData) = v; return *this;
};
private:
typedef boost::fusion::map <
std::pair<Name, std::string>,
std::pair<GivenName, std::string>,
std::pair<Age, unsigned short>
> data_type;
data_type mData;
};
It's really fun to use:
Person p;
p.set(name, "Rabbit").set(givenName, "Roger").set(age, 22);
Well, I myself prefer indexing by classes than by indices, because I can convey meaning as well as adding type checking ;)
Might I recommend using the Boost library's extensive (and well-tested and cross-platform) set of template-magicky classes? It sounds like what you're looking for is boost::tuple. Any time you can get away with not writing your own code—especially in a complicated situation with templates—you should use someone else's.
As others mentioned, you probably should be able to get where you want by reusing existing implementations from Boost or elsewhere.
If you would be doing something that can't be done using those or if you're curious:
try to keep the pseudo-variadic templates out of the implementation
use type-lists instead to allow for recursive meta-functions etc.
use pseudo-variadic templates as an interface if needed that forwards
to the implementation
do as much at compile-time as possible, especially checks for indices etc.
A simple approach, utilizing MPL for convenience could look something like this:
template<class Types, size_t N> struct holder
// recursively derive from holder types:
: holder<Types, N-1>
{
typename boost::mpl::at_c<Types,N>::type value;
};
// specialization that terminates the recursive derivation:
template<class Types> struct holder<Types,0> {
typename boost::mpl::at_c<Types,0>::type value;
};
template<class Types>
class AutoClass
// recursively derive from holder types:
: holder<Types, boost::mpl::size<Types>::value-1>
{
enum { n = boost::mpl::size<Types>::value };
public:
template<size_t N, class U> void set(const U& u) {
// index check at compile time:
BOOST_STATIC_ASSERT((N < n));
// cast to responsible holder base:
static_cast<holder<Types,N>*>(this)->value = u;
}
template<size_t N> typename boost::mpl::at_c<Types,N>::type get() const {
// index check at compile time:
BOOST_STATIC_ASSERT((N < n));
// cast to responsible holder base:
return static_cast<const holder<Types,N>*>(this)->value;
}
};
Usage:
typedef boost::mpl::vector<int,std::string> Types;
AutoClass<Types> a;
a.set<0>(42);
assert(a.get<0>() == 42);
a.set<1>("abcde");
assert(a.get<1>() == "abcde");
Keep in mind that this can still be wrapped with pseudo-variadic templates for end-user-convenience.
You need to implement for <nothing, nothing...> because of your base case. Consider:
template <typename W> W get(int n)
{
if (n <= 0)
return V;
else
return AutoClass<T2,T3,T4,T5,T6>::get(n-1);
}
Consider what happens when you call this function on a full AutoClass with an n of 5. It creates an autoclass with 5 members and calls with n = 4....and again until it reaches this point:
template <typename W> W get(int n) // current autoclass is <T6,nothing,nothing...>
{
if (n <= 0)
return V;
else
return AutoClass<T2,T3,T4,T5,T6>::get(n-1); // this is <nothing, nothing...>
}
Sure, the call to this autoclass won't happen but the compiler has to compile that code anyway because you've told it to.
You also need to make an AutoClass<nothing,...>::get because n could be 1093.
I don't see a way out of this with your current interface. If you put the n in the template argument you could make a special case that wouldn't do this. In this case you cannot. I think you're going to run into a lot of issues because you've chosen this interface that are going to be rather difficult to solve. For example, what happens when W is 'int' but AutoClass::get(n-1) returns a double or worse, something totally incompatible?