I want to create a template class for generic operators. The class will have two structs representing a value as input:
struct Value {
DataType type;
size_t dataSize;
char* data;
};
I already have written a type deduction with oldschool switch-cases. After a cast of the data-ptr to the type, I want to apply an operation on the input values like this:
template<class Operation>
class ApplyOperation {
Value* operator()(const Value* a, const Value* b) const {
//find type of a and b
//cast a and b to their types
Operation<aT,bT> op;
return op(a,b);
}
};
Now I could write for each operation a little struct like this:
template<class A, class B>
struct Add {
A operator()(A a, B b) const { return a + b; }
};
I have seen a boost class called operators: http://www.boost.org/doc/libs/1_59_0/libs/utility/operators.htm
which I want to use for my purpose. But I don't know how to integrate it since the operators in the structs are no functors. So would it be possible to use it like this?:
ApplyOperation<boost::addable::operator+> add;
add(a,b);
Actually I'm trying it for testing with this class:
template<template<class T, class U, class...> class OperatorClass,class F>
struct ApplyOperator {
template<class T, class U>
T foo(T a, U b) {
OperatorClass<T,U> opClass;
return opClass.operator+(a,b); //this works of course
}
};
What I want to get is this:
template<template<class T, class U, class...> class OperatorClass,class F>
struct ApplyOperator {
template<class T, class U>
T foo(T a, U b) {
OperatorClass<T,U> opClass;
return opClass.F(a,b);
}
};
Instantiated like that:
ApplyOperation<boost::addable, operator+> add;
This doesn't work of course because of the unknown type operator+. So how can I call the operator+-function with templates?
Is there a way to get this solved?
I am not sure I fully understood the question. But it looks like you are trying to provide an object instance (not type) to your template ApplyOperator. Since operator+ is definitely not a type and not an integral constant, it can not be used as a template argument in no way. What you will have to do is to make an operation an argument to the constructor, not the type of the object.
Related
I have a pair of class template declarations like this:
template<typename T, template<typename W> class X>
struct B {
bool operator()(const T& left, const T& right)
{ return X<W>()(left, right); }
};
template<template<typename T> class X, typename Q>
struct A {
bool operator()(const int a, const int b)
{
return B<Q, X>()(a, b);
}
};
I can create A<std::greater, int>, A<std::less, int> and it works as I want.
Is it possible to create a class that will contain a template passed in like std::greater and still be able to be passed like std::greater itself in the example above?
Something like this:
template <template <typename T> class Class>
class Wrapper
{
operator()(const int, const int) { return Class<?what's here?> (value, value); }
};
I would like to pass my Wrapper to an unchanged A
A<Wrapper<std::less>, long>
In other words, I want to imitate a template passed to my wrapper, to be compatible with actual version of class A.
The short answer is no, not quite like you want it to be. The first argument of A must be a template name. But when you add arguments and write Wrapper<std::less>, you get a class type. It is no longer a template. Think of it this way, A expects a cookie cutter, but you pass a cookie made from the cutter instead.
That's not to say you can't turn a template into another template, but it won't be quite so opaque. The solution is to add a member template to Wrapper. Then Wrapper<std::less>, despite being a class type, will have a member that is a template. And you can pass that in to A.
template <template <typename T> class Class>
struct Wrapper
{
template<typename U> // member template
struct temp {
bool operator()(const int v1, const int v2)
{ return Class<U>()(v1, v2); }
};
};
This enables you to write A<Wrapper<std::less>::temp, long>.
Check it out live.
Assume the following situation:
Type A and type B, B can be implicitly converted to A but the opposite is untrue.
I have a function
template<class T>
void do_stuff(T a, T b);
I want to call said function as such:
do_stuff(A{}, B{});
The problem here is that the compiler can't deduce the type and instead says:
template argument deduction/substitution failed
I can call my function like this:
do_stuff<A>(A{}, B{});
But this is more annoying for the user.
Alternatively I can do something like this:
template<class T, class M>
void do_stuff(T a, M b);
But then b goes on its merry way to be of type B (with the prior invocation).
Ideally I would like something like:
template<class T, class M = T>
void do_stuff(T a, M b);
Or:
template<class T#INSERT MAGIC SO THAT T IS DEDUCED AS BEING THE TYPE OF ARGUMENT NR 1#>
void do_stuff(T a, T b);
Is such a thing possible ?
Wrap b in a non-deduced context. That way, only a will be deduced and b must be converted to that type.
template <class T> struct dont_deduce { using type = T; };
template <class T> using dont_deduce_t = typename dont_deduce<T>::type;
template<class T>
void do_stuff(T a, dont_deduce_t<T> b);
There is answer in C++11: std::common_type
http://en.cppreference.com/w/cpp/types/common_type
template<typename A>
void f_impl(A a, A b)
{
}
template<typename A, typename B>
void f(A a, B b)
{
f_impl<typename std::common_type<A, B>::type>(a, b);
}
struct Z
{
};
struct W
{
operator Z();
};
int main()
{
f(1u, 1l); //work
f(W{}, Z{});
f(Z{}, W{}); //and this work too
}
https://godbolt.org/g/ieuHTS
It's certainly possible, just with a little delegation. You've made the problem pretty easy by specifying that you always want the inferred type to be the type of the first argument, so all we need to do is drop a little hint to the compiler.
template <class T>
void do_stuff_impl(T a, T b) {
cout << "Doing some work..." << endl;
}
template <class T, class S>
void do_stuff(T a, S b) {
do_stuff_impl<T>(a, b);
}
Now the user can call do_stuff with any two arguments, and C++ will try to implicitly cast the second argument to match the type of the first. If the cast isn't valid, you'll get a template instantiation error. On GCC, it says cannot convert ‘b’ (type ‘A’) to type ‘B’, which is pretty accurate and to the point. And any compiler worth its salt is going to be able to inline that delegated call, so there should be negligible overhead.
another way, seeking to express intent declaratively:
#include <type_traits>
// a B
struct B{};
// an A can be constructed from a B
struct A{
A() {};
A(B) {};
};
// prove that A is constructible from B
static_assert(std::is_convertible<B, A>::value, "");
// enable this function only if a U is convertible to a T
template<
// introduce the actors
class T, class U,
// declare intent
std::enable_if_t<std::is_convertible<U, T>::value>* = nullptr
>
void do_stuff(T, U)
{
}
int main()
{
// legal
do_stuff(A{}, B{});
// does not compile
// do_stuff(B{}, A{});
}
update:
to force the conversion, a lambda can be used:
// enable this function only if a U is convertible to a T
template<class T, class U,
std::enable_if_t<std::is_convertible<U, T>::value>* = nullptr
>
void do_stuff(T a, U b)
{
return[](T& a, T b) -> decltype(auto)
{
}(a, b);
}
Take the following class hierarchy:
template<typename T>
class Foo {
public:
T fooMethod() { ... }
};
class Moo : public Foo<bool> {
...
};
If I now somewhere write Moo::fooMethod the compiler will deduce Foo<bool>::fooMethod. How can I deduce Foo<bool> as parent of fooMethod myself before compile time?
Motivation: the compiler will not allow Foo<bool>::fooMethod to be passed as template parameter for bool (Moo::*)() since it will be of type bool (Foo<bool>::*)() in that context. But since I have multiple inheritance I dont know what parent fooMethod will be in, it must be deduced.
If I understand the problem correctly, it is possible to deduce the class a member function is defined in, using the following trait:
template<typename>
struct member_class_t;
template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...)> { using type = C; };
template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...) const> { using type = C const; };
// ...other qualifier specializations
template<typename M>
using member_class = typename member_class_t <M>::type;
after which you can write
member_class<decltype(&Moo::fooMethod)>
giving Foo<bool>.
To define member_class more generally, you should take into account volatile and ref-qualifiers as well, yielding a total of about 12 specializations. A complete definition is here.
I'm trying to use templates with multiple to pass data onto a function, but using only the first template argument as a filter. Something like this:
template <typename A, typename B>
class Component {
};
template <typename A>
class Context {
public:
void add(Component<A, void *> comp) {
}
}
typedef struct Foo { int x; } Foo;
typedef struct Bar { int y; } Bar;
Context<Foo> *context = new Context<Foo>();
Component<Foo, Bar> *comp = new Component<Foo, Bar>();
context->add(comp); // error
But the compiler complains that it cannot convert Component<Foo, Bar> to Component<Foo, void *>. Is there a way to accomplish this?
I think what you probably need to do is change the signature of the 'add' method:
template <typename A>
class Context
{
public:
template<class B>
void add(Component<A, B> comp)
{
}
};
However, I don't know the details of your problem so this is a mere guess.
I'm trying to use templates with multiple to pass data onto a function, but using only the first template argument as a filter. [...] But the compiler complains that it cannot convert Component to Component. Is there a way to accomplish this?
Well, your filter works doesn't it: your add function will only match a Component whose second template parameter is void*, and you're providing Bar. What else could you possibly expect? If you want it to handle other "second-parameters" as well, either remove the filter, provide an fallback function for it to match, or some kind of conversion.
Yes, add a converting copy constructor to your Component:
template<class U, class V>
Component(Component<U,V> const& other){
// ...
};
But that is still refineable with the appropriate enable_if SFINAE guard:
// <tr1/type_traits> for C++03
#include <type_traits> // for C++0x
template<class T, class U>
struct can_convert{
// std::tr1::... for C++03
static bool const value =
std::is_same<T,U>::value || std::is_convertible<T,U>::value;
};
template<class C1, class C2>
struct ice_and{
static bool const value = C1::value && C2::value;
}
// define for clarity and brevity
#define IF_CAN_CONVERT(A,B,U,V) \
typename std::enable_if<ice_and<can_convert<A,U>,can_convert<B,V> > >::type* = 0
template<class U, class V>
Component(Component<U,V> const& other, IF_CAN_CONVERT(A,B,U,V)){
// ...
};
I already asked two questions related to what I'm trying to do (one resolved, one of which I will close soon). I know that C++ template instantiation does not allow any implicit conversions (see for example this comment), but I would like to simulate it.
Suppose I have the following skeleton code:
template <class T>
struct Base_A{
virtual void interface_func() const = 0;
};
template <class T>
struct Derived_A : public Base_A<T>{
typedef T value_type;
void interface_func() const{}
};
template <class T>
struct Base_B{
virtual void interface_func() = 0; // note: non-const
};
template <class T>
struct Derived_B : public Base_B<T>{
typedef T value_type;
void interface_func(){}
};
template <class BType>
struct Adapter : public Base_A<typename BType::value_type>{
BType &ref_B;
Adapter(BType &inst_B):ref_B(B_inst){}
void interface_func() const{} // does stuff with ref_B to simulate an A
};
template <class Should_Always_Be_Base_A>
void f(const Should_Always_Be_Base_A &arg){
// Only Base_A can be passed in by const ref
// Passing in a Base_B by const ref would not work.
}
Derived_A<int> A;
Derived_B<int> B;
f(A); // passes in A by const ref
f(B); // I want to pass in Adapter<Derived_B<int> >(B)
I want the template parameter for function f to always be a derived class of Base_A or an Adapter. The answer to restricting the type of arg can be done, but the implicit conversion to an Adapter cannot. Is there any way to do this? The net result is I want to be able to call f as f(A) or f(B), and in both cases I need to know the actual derived type of A or B within f (f cannot just see a reference to the base class).
Aside:
Presently, I just have f(A) working, and f(B) actually calls an overload which performs the Adapter construction, but I have other functions which take N arguments, each of which can be A or B, so I would need 2^N overloads.
For the curious, this is in application to the matrix library I'm working on. Base_A represents the base matrix type, and Base_B represents the base matrix-view type. For operations which will modify a matrix argument, I need to pass in the matrix by non-const reference or a modifiable matrix-view by const-ref. The adapter is just a trivial matrix-to-view adapter. So for example, I currently have a function like
Scale(const MatrixViewBase<T> &Mview, const T &scale_factor){
// does the actual work
}
Scale(MatrixBase<T> &M, const T &scale_factor){
Scale(Adapter<MatrixBase<T> >(M), scale_factor);
}
It's tedious and error prone to make 2^N copies of all these functions just to create the needed overloads to handle both views and non-views. As is, this is not good enough since I want Scale to be able to know the full derived type of Mview, not just the base class, because I will potentially generate instances of types dependent on Mview.
Edit 1: Changed all B types to have non-const interface functions. This was the original intent, so apologies for any confusion.
Edit 2: Have this working code, still requires 2^N overloads, but I can live with it unless someone suggests how to deal with that.
#include <iostream>
template <class T>
struct ReadableMatrix{
typedef T value_type;
};
template <class T>
struct WritableMatrix{
typedef T value_type;
};
template <class T>
struct WritableMatrixView{
typedef T value_type;
};
template <class T>
struct Matrix : public WritableMatrix<T>{
typedef T value_type;
typedef ReadableMatrix<T> readable_matrix;
typedef WritableMatrix<T> writable_matrix;
};
template <class T>
struct MatrixView : public WritableMatrixView<T>{
typedef T value_type;
typedef ReadableMatrix<T> readable_matrix; // not really used; needs an adapter before using
typedef WritableMatrixView<T> writable_matrix;
};
template <class T, class R>
struct IsReadableMatrix{
};
template <class T, class R>
struct IsReadableMatrix<ReadableMatrix<T>, R>{
typedef R type;
};
template <class T, class R>
struct IsWritableMatrix{
};
template <class T, class R>
struct IsWritableMatrix<WritableMatrix<T>, R>{
typedef R type;
};
template <class T, class R>
struct IsWritableMatrixView{
};
template <class T, class R>
struct IsWritableMatrixView<WritableMatrixView<T>, R>{
typedef R type;
};
template <class TA, class TB>
typename IsReadableMatrix<typename TA::readable_matrix,
typename IsWritableMatrixView<typename TB::writable_matrix,
void
>::type>::type
Copy(const TA &A, const TB &B){
std::cout << "Here" << std::endl;
}
template <class TA, class TB>
typename IsReadableMatrix<typename TA::readable_matrix,
typename IsWritableMatrix<typename TB::writable_matrix,
void
>::type>::type
Copy(const TA &A, TB &B){
std::cout << "Here2" << std::endl;
}
int main(){
Matrix<int> M, M2;
MatrixView<int> V, V2;
Copy(M, M2);
Copy(V, V2);
Copy(M, V);
Copy(V, M);
}
Do you need you base classes to be templates? Can you inject even "more base" nontemplate class?
If yes, you can do something like that:
struct Base_A{
virtual void interface_func() const = 0;
};
template <class T>
struct Derived_A : public Base_A{
typedef T value_type;
void interface_func() const{}
};
struct Base_B{
virtual void interface_func() const = 0;
};
template <class T>
struct Derived_B : public Base_B{
typedef T value_type;
void interface_func() const{}
};
struct Adapter
{
const Base_A* pA;
const Base_B* pB;
Adapter(const Base_B &inst_B) : pB(&inst_B), pA(0){}
Adapter(const Base_A &inst_A) : pA(&inst_A), pB(0){}
void interface_func() const
{
if( 0 != pA )
pA->interface_func();
else if( 0 != pB )
pB->interface_func();
}
};
void f(const Adapter &arg)
{
arg.interface_func(); // will call proper interface_func
}
int main()
{
Derived_A<int> A;
Derived_B<int> B;
f(A);
f(B);
}
Try the following:
template <template <typename> View, typename T>
struct Adapter
{
// Leave empty to cause errors if used, or you could
// provide a generic adapter for View<typename T::value_type>
}
// Partial specialization for a given base.
template <typename T>
struct Adapter<MatrixView, T> : MatrixView<typename T::value_type>
{
const T& t;
Adapter (const T& t)
: t(t)
{}
void some_virtual()
{
// Do stuff
}
}
template <template <typename> View, typename T>
const View<T>& adapt (const View<T>& v)
{
return v;
}
template <template <typename> View, typename T>
View<T> adapt (const T& t)
{
return Adapter<View, T>(t);
}
template <typename T, typename U>
foo(const MatrixViewBase<T> &Mview, const MatrixViewBase<U> &Mview2);
template <typename T, typename U>
foo (const T& t, const U& u)
{
return foo(adapt<MatrixViewBase>(t), adapt<MatrixViewBase>(u));
}
I put const in everywhere I could; you don't have to use it in every situation if it's not appropriate. You can use specializations of Adapter for a given T to further tailor the behavior.
Interestingly enough, this is the first time I've ever recommended template template parameters.
I have not looked into the details of a templated solution, but while you are at it, you can check the boost preprocessor library to help you in defining the 2^N variations of the template. This won't be nice on compile time, but it will be better than manually creating the variations.
I had to do this a while ago and the easiest (to maintain) solution I came up with was to have only one class (Matrix) that knows if it owns it's own data or is a view of someone else's data. E.g.,
Matrix A(n,m); //Creates a new matrix of size (n,m)
Matrix B=View(A); //Creates a matrix that's a view into A
Matrix C=View(pData,n,m); //Creates a matrix thats a view of data in a pointer that someone else owns
Foo(A);
Foo(B);
Foo(C);
It makes writing the Matrix class a little more difficult, but then later anyone who uses a Matrix, just uses it as a matrix, they don't need to care if it's a view or not.
Edited to add:
Why not just let BLAS manage the transpose for you? In the end, any of the BLAS functions are just going to want a pointer to a contiguous chunk of memory. So as long as your Matrix class knows how to get to that memory you're good. If the Matrix class has it's own isTransposed flag inside then you can do something like this:
Matrix A(n,m);
Matrix B=TransposedView(pData,m,n);
Matrix C=A*B;
Matrix& operator*(const Matrix& lhs, const Matrix& rhs)
{
Matrix result(lhs.Rows(),rhs.Cols()); //or did i get that backwards :)
char TransL=lhs.IsTransposed()?'T':'N';
char TransR=rhs.IsTransposed()?'T':'N';
_dgemm(TransL, TransR, ..., lhs.Data(), ..., rhs.Data(), ..., result.Data());
return result
}