I am working on making an expression class:
template<typename T, typename U>
class expression
{
public:
expression(T vala, U valb, oper o){val1 = vala; val2 = valb; op = o;}
operator bool{return(val1 op val2);}
private:
T val1;
U val2;
oper op;
};
as you can see, this is somewhat pseudocode, because I need an operator class. My original thought was to create an array of all possible operators, and then convert it through a string, but that wouldn't work because of the sheer number of operators, and how to convert it to a string except through a two dimensional array, where n[0][0] has the first operator, and n[0][1] has that operators string.
Does anybody have any suggestions to adding an operator value to my expression class?
Similar methods are used in c++ expression templates techniqueue.
You create expression as a class with a method such as apply or evaluate. This method takes the parameters and applies the expression.
Have a look what expression templates are using.
http://www.angelikalanger.com/Articles/Cuj/ExpressionTemplates/ExpressionTemplates.htm
https://www.cct.lsu.edu/~hkaiser/spring_2012/files/ExpressionTemplates-ToddVeldhuizen.pdf
As an example in your case:
struct isEqual
{
template <typename T, typename U>
bool operator()(T a, U b)
{
return a == b;
}
};
template <typename T, typename OP>
struct expression
{
T& a;
T& b;
OP& op;
expression(T a, T b, OP op) : a(a), b(b), op(op) {}
void eval() { op(a,b); }
};
int main()
{
expression<int, isEqual> exp(1,2,isEqual());
exp.eval();
}
Maybe a function pointer. Instead of ...
operator bool{return(val1 op val2);}
... code it as ...
operator bool{return op(val1, val2);}
... in which case op can be a pointer to a (any) function which takes two parameters and which returns bool.
template<typename T, typename U>
class expression
{
public:
//define pointer-to-function type
typedef bool *oper(const T& val1, const U& val2);
... etc ...
I'm not entirely sure what you're asking, but if you are trying to overload an arbitrary string as an operator, you can't. There is a finite set of operators that you can overload in c++
see here: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
What you should do is overload operator() in oper to create a function object and return op(val1, val2) instead.
You can use the functional standard library and take your argument as a:
std::tr1::function<bool (T,U)>
ie:
#include <functional>
template<typename T, typename U>
class expression
{
public:
expression(T vala, U valb, oper o) : val1(vala), val2(valb), op(o)
{ }
operator bool{return op(val1, val2);}
private:
T val1;
U val2;
std::tr1::function<bool (T,U)> op;
};
Then, to create a expression:
#include <functional>
expression<int, int> foo(4,3, std::tr1::bind(greater()));
Here's a tutorial
Related
This is the basic implementation I'm using for expression templates, based on the CRTP which allows me to conveniently combine multiple types of operations without also asking everything to be an expression tree.
template<typename E>
struct OpExpression
{
auto eval(iter_type n) const
{
return static_cast<E const&>(*this).eval(n);
}
};
template<typename T>
struct OpFrame : OpExpression<OpFrame<T>>
{
T *ptr;
OpFrame(T *ptr) : ptr{ ptr } {}
T eval(iter_type n) const
{
return ptr[n];
}
};
template<typename T>
struct OpLiteral : OpExpression<OpLiteral<T>>
{
T value;
OpLiteral<T>(T value) : value{ value } {}
T eval(iter_type) const
{
return value;
}
operator T() const
{
return value;
}
};
Here is a class to apply the addition between two values (and an operator overload to make it pretty):
template<typename E1, typename E2>
struct OpFrameAdd : OpExpression<OpFrameAdd<E1, E2>>
{
OpFrameAdd(E1 const a, E2 const b) : a{ a }, b{ b } {}
auto eval(iter_type n) const
{
return a.eval(n) + b.eval(n);
}
protected:
E1 const a;
E2 const b;
};
template<typename E1, typename E2>
auto operator+(OpExpression<E1> const& a, OpExpression<E2> const& b)
{
auto v = OpFrameAdd<E1, E2>(*static_cast<const E1*>(&a), *static_cast<const E2*>(&b));
return v;
}
To provide some more detail/context; I have an array holding a bunch of values (could be of various types), and an arithmetic expression defining how I want to transform that array into another one. However, this transformation is not concrete, so I'm using the expression tree as something I can pass to objects that will then handle it in different ways (i.e. I have to wait to evaluate it). Additionally, I only want to define the expression once.
I'm wondering, if based on this design, I can introduce literals (without casting to an OpLiteral) to my expressions? For example:
double arr[100]{ 0 };
OpFrame arr_t(arr);
// I can do this
auto ev1 = arr_t + arr_t + arr_t + OpLiteral(2.0);
// But I would prefer to do this
auto ev2 = arr_t + arr_t + arr_t + 2.0;
Based on my question here, I know 2.0 won't automatically cast to the correct type, but the solution is also not compatible with this design (it causes either an ambiguous call, or in bigger expressions, mixes up the tree by applying the generic template rather than one based on OpExpression<T>).
How I had tried to implement that solution:
template<typename E1, typename T>
auto operator+(OpExpression<E1> const& a, T b)
{
auto v = OpFrameAdd<E1, OpLiteral<T>>(*static_cast<const E1*>(&a), OpLiteral<T>(b));
return v;
}
template<typename E2, typename T>
auto operator+(T a, OpExpression<E2> const& b)
{
auto v = OpFrameAdd<OpLiteral<T>, E2>(OpLiteral<T>(a), *static_cast<const E2*>(&b));
return v;
}
So my questions are:
Is it possible to augment the design to use the literal in the preferred way? If not, is this is just a limitation of the templates/design I chose? (Casting to OpLiteral is still a lot easier than making a new operator overload for each type and for both sides). More broadly, is there a known (different) design to deal with this problem? Have I applied this design correctly to the problem?
EDIT
With the given design, it doesn't appear possible to accept and convert another type implicitly. Ultimately, it seems the problem can be phrased as: I want to have an operation between 1) A parent class and another parent class; 2) A parent class an any other object; 3) Any class and that parent class. Obviously this is inherently problematic.
For instance, when I attempted to remedy the ambiguous call in the above attempt, it instead results in operations between children of OpExpression becoming a template argument of OpLiteral. This is because instead of resolving the 'correct' operator (i.e. applying operator with both argument types of OpExpression), it will choose the one with the more generic argument type.
The conclusion is that as it is, this is simply a limitation of the design (and for good reason).
However, suppose I have a complete list of all the literal types I would want to use in an expression. If I don't want to create individual template specializations for each one, how would I modify the overloaded operator to use that? Would I instead have to modify the classes of OpExpression?
Suppose the following snippet:
template <class T>
void fct(T* a, T* b){
// do something
}
A a;
fct(&a, nullptr); // Problem here!
This makes trouble, since the call arguments are of type A* and nullptr_t and so the compiler can not deduce template parameter T.
Generally, I can imagine several ideas how to solve this:
Define A* b = nullptr and use fct(&a, b)
Define an overload with one argument for fct for the nullptr case
Use fct(&a, static_cast<A*>(nullptr))
Or is there a more clean solution, like the creation of a something like a "typed nullptr"?
Just make the second argument a non-deduced context, e.g:
template <class T>
void fct(T* a, std::remove_reference<T*>::type b) {
I would also suggest the following solution:
template <class T, class U>
void fct(T* a, U b){
T* b2 = b;
// do something
}
A a;
fct(&a, nullptr);
This allows for a wider usage of fct, but maybe that's exactly what you want to.
For example, consider
class A {};
class B : public A {};
...
A a;
B b;
fct(&a, &b); // calls fct<A>
// the following will not compile:
// fct(&b, &a);
You can use the following code:
#include <type_traits>
template<class T>
void f_impl(T*, T*)
{
std::cout << typeid(T).name() << "\n";
}
template<class T, class U>
void f(T l, U r)
{
static_assert((std::is_same<T, U>::value && std::is_pointer<T>::value) ||
(std::is_same<T, std::nullptr_t>::value && std::is_pointer<U>::value) || // First non-null
(std::is_same<U, std::nullptr_t>::value && std::is_pointer<T>::value) // Second non-null
, "");
using P = typename std::conditional<std::is_same<T, std::nullptr_t>::value, U, T>::type;
f_impl<typename std::remove_pointer<P>::type>(l, r);
}
int main()
{
int i;
f(&i, nullptr);
f(nullptr, &i);
// f(i, nullptr); // won't compile - non-pointer
f(&i, &i);
double d;
// f(&i, &d); // - won't compile
}
This version tests will allow to call f with one nullptr (but not both), or with two pointers to the same type. With c++14 you can also use things like std::conditional_t, std::remove_pointer_t and std::is_null_pointer to remove some biolerplate.
As the question already states, nullptr in fact has a type: std::nullptr_t. So just add an explicit overload for specifically that case:
template <class T>
void fct(T* a, std::nullptr_t b) { return fct<T>(a,static_cast<T*>(b)); }
No need to have some template argument class U for that.
template <class T> struct greater : binary_function <T, T, bool> {
bool operator() (const T& x, const T& y) const {
return x > y;
}
};
I found this definition of "Function object class for greater-than inequality comparison" in STL library.
Can somebody please explain to me how this code works and compiles?
template <class T> // A template class taking any type T
// This class inherit from std::binary_function
struct greater : binary_function <T, T, bool>
{
// This is a struct (not a class).
// It means members and inheritens is public by default
// This method defines operator() for this class
// you can do: greater<int> op; op(x,y);
bool operator() (const T& x, const T& y) const {
// method is const, this means you can use it
// with a const greater<T> object
return x > y; // use T::operator> const
// if it does not exist, produces a compilation error
}
};
here is the definition of std::binary_function
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
this allows you to access the types defining the binary_function
greater<int> op;
greater<int>::result_type res = op(1,2);
which is equivalent to
std::result_of<greater<int>>::type res = op(1,2);
It's a template class that can be instantiated with one type argument. So you can say greater<int>, greater<my_class>, etc. Each of those instantiations has an operator() that takes two arguments of type const T& and returns the result of comparing them.
greater<int> gi;
if (gi(1, 2)) {
// won't get here
} else {
// will get here
}
I don't know have much you know about template programming and functors.
Let's start with functors :
struct greater {
bool operator()(const int& x, const int& b) const {
return x > y;
}
greater g;
g(2,3); // returns false
g(3,2); // returns true
So functors mock a function you could have as well implemented bool g(int x, int y){return x>y;} and used it the same way.
The nice thing about functors, is that you can also store some data when working on more complexe data structure.
Then there is the template part : you want to write the same functor for any type, you don't care if the type is an int, a float, a complexe object, the code will be the same. That's what the template part is for.
Here, the context of polymorphic is expecting 'Derived' from 'Base&.
Given
class P { };
class Q : public P { };
auto operator + (const P& p, int x) -> DYNAMIC_DECLTYPE(P) {
DYNAMIC_DECLTYPE(P) p2(p);
p2.func(x);
return p2;
}
Is there a way to have DYNAMIC_DECLTYPE working? I want to use this form instead of
template <typename T> T operator + (const T& t, int x)
or have a potentially long list of
if (!strcmp(typeid(p).name(), typeid(derived()).name()) { ... }
because the latter cannot be used to restrict T to P or subclasses thereof (prove me wrong, if possible).
What you are trying to do is in every sense of the word a template pattern: You have an unbounded family of return types with matching function argument types. This should simply be a straight template.
If you want to restrict the permissible types, you should add some typetrait magic. Perhaps like this:
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_base_of<P, T>::value, T>::type
operator+(T const & t, int x)
{
T s(t);
s.func(x);
return s;
}
(If func returns a reference, you can shortcut this to return T(t).func(x);.)
I have this template function:
template <class P>
double Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
but I want to avoid forcing the return type to double all the time -- P::x and P::y could be ints too, and I need this function in both situations. Is there a way to specify the type of x and y, something like this?
//doesn't compile; can't deduce template argument for T
template <typename T, class P>
T Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
edit: My compiler is VC2005
edit2: sorry to forget to mention: Unfortunately I can't modify the implementation of the structs for P; one of the point types I deal with is MFC/ATL's CPoint, which are hard-coded as { long x; long y; }.
Compiler cannot deduce return-type of function template, from function argument. Type deduction is done with function arguments only.
In C++03, you can define typedef in your class as:
struct A //suppose A is going to be type argument to your function template
{
int x, y; //I'm assuming type of x and y is same!
typedef int value_type; //type of x and y!
};
And then you've to re-write your function as:
template <class P>
typename P::value_type Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
Notice the return-type now, its a dependent type. Its :
typename P::value_type
The keyword typename is required here.
Alright, as you said you can't modify your structs, then you can use traits instead. Here is how this can be done:
template<typename T> struct PTraits;
//Suppose this is your type which you can't modify
struct A //A is going to be type argument to your function template
{
long x, y;
};
//specialization: defining traits for struct A
template<>
struct PTraits<A>
{
typedef long value_type; //since type of A::x and A::y is long!
};
And your function template would look like this:
template <class P>
typename PTraits<P>::value_type Determinant(const P & a, const P & b, const P & c) {
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
Notice the return-type; its slightly different now:
typename PTraits<P>::value_type
Again, value_type is a dependent name, so the keyword typename is required.
Note that you've to specialize PTraits<> for each type which you pass to the function template, as I did.
I like to use a traits style approach to this:
template<typename T> struct DeterminantReturnInfo {};
template<> struct DeterminantReturnInfo<MyType> { typedef MyOtherType ReturnType; }
template< typename T >
typename DeterminantReturnInfo<T>::ReturnType Determinant( const P & a, const P & B, const P & c)
{
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
If you want it to default to double then you just add typedef double ReturnType; to the initial template.
If you're using Visual Studio 2010 or GCC 4.5+, you can use the trailing return type form:
template<class P>
auto fun(const P& a) -> decltype(a.x + a.y){
return a.x + a.y;
}
Thanks to decltype we automatically get the right return type. Also, the computation is still only done once in the body, not in the trailing return.
Check your return Type its of type member variable x/y . You might not returning so type T.