C++ Move assignment operator - c++11

I am attempting to use operator overloading of the '&' and '|' and '|=' operators of C++ inorder to create a BNF (Backus Naur Form) embedded in C++.
The two significant classes in this embedded BNF are class Terminal and class NonTerminal.
As example Snippet, consider the BNF description of a list of the characters 'a' or 'b':
Terminal _a('a'), _b('b');
NonTerminal list, token;
token |= _a | _b;
list |= token | token & list;
// Parse a string of 'a's and 'b's
if(list.match("baabaabaa"))
cout << "matched!!!";
else
cout << "failed!!!";
// Test the token nonterminal
token.match("a");
The class definitions are as follows: They don't do anything at the moment but serve as a test of the logic.
using namespace std;
class Sequence;
class Production;
class Base {
Base() {}
virtual ~Base() {}
friend Sequence operator & (const Base& lhs, const Base& rhs);
friend Production operator | (const Base& lhs, const Base& rhs);
virtual bool match(string) const { return false; }
};
class Terminal : public Base {
char token;
public:
Terminal(char c) : token(c) {}
virtual ~Terminal() {}
virtual bool match(string s) const { return true; }
};
class Sequence : public Base {
const Base& lhs;
const Base& rhs;
public:
Sequence(const Base& lhs, const Base& rhs) : lhs(lhs), rhs(rhs) {}
virtual ~Sequence() {}
virtual bool match(string s) const { return lhs.match(s) && rhs.match(s); }
};
class Production: public Base {
const Base& lhs;
const Base& rhs;
public:
Production(const Base& lhs, const Base& rhs) : lhs(lhs), rhs(rhs) {}
virtual ~Production() {}
virtual bool match(std::string s) const { return lhs.match(s) || rhs.match(s); }
};
The last class definition, NonTerminal, is where I am having trouble. And the trouble involves C+11 move semantics.
class NonTerminal : Base {
Base dummy; // Needed to make initialization work.
Base& ref; // Or maybe Base&& ref or possibly Base ref or could it be Base* ref?
NonTerminal() : ref(dummy) {}
virtual ~NonTerminal() {}
// Used when rhs is of type Sequence or Production
void operator |= (Base&& rhs) {
// The desired action is to capture rhs and keep it in memory.
ref = move(rhs);
}
// Used when rhs is of type Terminal
void operator |= (const Base& rhs) {
// The desired action is to reference rhs.
ref = rhs;
}
virtual bool match(string s) { return ref.match(s); }
};
The code that the above example is based on compiles but when 'list.match()' is called, it calls the method Base::match() and not Production::match() which is the expected behaviour. In the same manner, calling token.match() also calls the method Base::match() and not Terminal::match(). So how do I get the correct overwritten match methods called and do it correctly for the rvalue received in the first operator |= method?
Thanks

Related

Composing boost::variant visitors for recursive variants

I have an application with several boost::variants which share many of the fields. I would like to be able to compose these visitors into visitors for "larger" variants without copying and pasting a bunch of code. It seems straightforward to do this for non-recursive variants, but once you have a recursive one, the self-references within the visitor (of course) point to the wrong class. To make this concrete (and cribbing from the boost::variant docs):
#include "boost/variant.hpp"
#include <iostream>
struct add;
struct sub;
template <typename OpTag> struct binop;
typedef boost::variant<
int
, boost::recursive_wrapper< binop<add> >
, boost::recursive_wrapper< binop<sub> >
> expression;
template <typename OpTag>
struct binop
{
expression left;
expression right;
binop( const expression & lhs, const expression & rhs )
: left(lhs), right(rhs)
{
}
};
// Add multiplication
struct mult;
typedef boost::variant<
int
, boost::recursive_wrapper< binop<add> >
, boost::recursive_wrapper< binop<sub> >
, boost::recursive_wrapper< binop<mult> >
> mult_expression;
class calculator : public boost::static_visitor<int>
{
public:
int operator()(int value) const
{
return value;
}
int operator()(const binop<add> & binary) const
{
return boost::apply_visitor( *this, binary.left )
+ boost::apply_visitor( *this, binary.right );
}
int operator()(const binop<sub> & binary) const
{
return boost::apply_visitor( *this, binary.left )
- boost::apply_visitor( *this, binary.right );
}
};
class mult_calculator : public boost::static_visitor<int>
{
public:
int operator()(int value) const
{
return value;
}
int operator()(const binop<add> & binary) const
{
return boost::apply_visitor( *this, binary.left )
+ boost::apply_visitor( *this, binary.right );
}
int operator()(const binop<sub> & binary) const
{
return boost::apply_visitor( *this, binary.left )
- boost::apply_visitor( *this, binary.right );
}
int operator()(const binop<mult> & binary) const
{
return boost::apply_visitor( *this, binary.left )
* boost::apply_visitor( *this, binary.right );
}
};
// I'd like something like this to compile
// class better_mult_calculator : public calculator
// {
// public:
// int operator()(const binop<mult> & binary) const
// {
// return boost::apply_visitor( *this, binary.left )
// * boost::apply_visitor( *this, binary.right );
// }
// };
int main(int argc, char **argv)
{
// result = ((7-3)+8) = 12
expression result(binop<add>(binop<sub>(7,3), 8));
assert( boost::apply_visitor(calculator(),result) == 12 );
std::cout << "Success add" << std::endl;
// result2 = ((7-3)+8)*2 = 12
mult_expression result2(binop<mult>(binop<add>(binop<sub>(7,3), 8),2));
assert( boost::apply_visitor(mult_calculator(),result2) == 24 );
std::cout << "Success mult" << std::endl;
}
I would really like something like that commented out better_mult_expression to compile (and work) but it doesn't -- because the this pointers within the base calculator visitor don't reference mult_expression, but expression.
Does anyone have suggestions for overcoming this or am I just barking down the wrong tree?
Firstly, I'd suggest the variant to include all possible node types, not distinguishing between mult and expression. This distinction makes no sense at the AST level, only at a parser stage (if you implement operator precedence in recursive/PEG fashion).
Other than that, here's a few observations:
if you encapsulate the apply_visitor dispatch into your evaluation functor you can reduce the code duplication by a big factor
your real question seems not to be about composing variants, but composing visitors, more specifically, by inheritance.
You can use using to pull inherited overloads into scope for overload resolution, so this might be the most direct answer:
Live On Coliru
struct better_mult_calculator : calculator {
using calculator::operator();
auto operator()(const binop<mult>& binary) const
{
return boost::apply_visitor(*this, binary.left) *
boost::apply_visitor(*this, binary.right);
}
};
IMPROVING!
Starting from that listing let's shave off some noise!
remove unncessary AST distinction (-40 lines, down to 55 lines of code)
generalize the operations; the <functional> header comes standard with these:
namespace AST {
template <typename> struct binop;
using add = binop<std::plus<>>;
using sub = binop<std::minus<>>;
using mult = binop<std::multiplies<>>;
using expr = boost::variant<int,
recursive_wrapper<add>,
recursive_wrapper<sub>,
recursive_wrapper<mult>>;
template <typename> struct binop { expr left, right; };
} // namespace AST
Now the entire calculator can be:
struct calculator : boost::static_visitor<int> {
int operator()(int value) const { return value; }
template <typename Op>
int operator()(AST::binop<Op> const& binary) const {
return Op{}(boost::apply_visitor(*this, binary.left),
boost::apply_visitor(*this, binary.right));
}
};
Here your variant can add arbitrary operations without even needing to touch the calculator.
Live Demo, 43 Lines Of Code
Like I mentioned starting off, encapsulate visitation!
struct Calculator {
template <typename... T> int operator()(boost::variant<T...> const& v) const {
return boost::apply_visitor(*this, v);
}
template <typename T>
int operator()(T const& lit) const { return lit; }
template <typename Op>
int operator()(AST::binop<Op> const& bin) const {
return Op{}(operator()(bin.left), operator()(bin.right));
}
};
Now you can just call your calculator, like intended:
Calculator calc;
auto result1 = calc(e1);
It will work when you extend the variant with operatios or even other literal types (like e.g. double). It will even work, regardless of whether you pass it an incompatible variant type that holds a subset of the node types.
To finish that off for maintainability/readability, I'd suggest making operator() only a dispatch function:
Full Demo
Live On Coliru
#include <boost/variant.hpp>
#include <iostream>
namespace AST {
using boost::recursive_wrapper;
template <typename> struct binop;
using add = binop<std::plus<>>;
using sub = binop<std::minus<>>;
using mult = binop<std::multiplies<>>;
using expr = boost::variant<int,
recursive_wrapper<add>,
recursive_wrapper<sub>,
recursive_wrapper<mult>>;
template <typename> struct binop { expr left, right; };
} // namespace AST
struct Calculator {
auto operator()(auto const& v) const { return call(v); }
private:
template <typename... T> int call(boost::variant<T...> const& v) const {
return boost::apply_visitor(*this, v);
}
template <typename T>
int call(T const& lit) const { return lit; }
template <typename Op>
int call(AST::binop<Op> const& bin) const {
return Op{}(call(bin.left), call(bin.right));
}
};
int main()
{
using namespace AST;
std::cout << std::boolalpha;
auto sub_expr = add{sub{7, 3}, 8};
expr e1 = sub_expr;
expr e2 = mult{sub_expr, 2};
Calculator calc;
auto result1 = calc(e1);
std::cout << "result1: " << result1 << " Success? " << (12 == result1) << "\n";
// result2 = ((7-3)+8)*2 = 12
auto result2 = calc(e2);
std::cout << "result2: " << result2 << " Success? " << (24 == result2) << "\n";
}
Still prints
result1: 12 Success? true
result2: 24 Success? true

Generate one method per type from variadic class template

I would like to have a variadic class template to generate one method per type, such that for example a class template like the following:
template <class T, class ... Ts>
class MyClass {
public:
virtual void hello(const T& t) = 0;
};
would make available the methods hello(const double&) and hello(const int&) when instantiated as MyClass<double, int> myclass;
Note that I want the class to be pure abstract, such that a derived class would actually need to do the implementation, e.g.:
class Derived : MyClass<double, int> {
public:
inline void hello(const double& t) override { }
inline void hello(const int& t) override { }
};
This problem is somewhat similar to this one, but I couldn't understand how to adapt it to my case.
EDIT
The recursion inheritance seems to be the right solution for me. How about this more complicated case, where the superclass has more than one method and a template argument is mandatory? Here is what I've tried (but I get error):
template <class MandatoryT, class OptionalT, class... MoreTs>
class MyClass : public MyClass<MandatoryT, MoreTs...> {
public:
virtual ~MyClass() {}
virtual char* goodmorning(const MandatoryT& t) = 0;
virtual bool bye(const MandatoryT& t,
const std::map<std::string,bool>& t2) = 0;
using MyClass<MandatoryT, MoreTs...>::hello;
virtual void hello(const OptionalT& msg) = 0;
};
template <class MandatoryT, class OptionalT>
class MyClass<MandatoryT, OptionalT> {
virtual void processSecondaryMessage(const OptionalT& msg) = 0;
};
template <class MandatoryT>
class MyClass<MandatoryT> {
virtual void processSecondaryMessage() = 0;
}
}
Basically what I want is that the derived class should have one or more types. The first one is used in other methods, while from the second onwards it should be used in hello(). If only one type is provided, an empty hello() is called. But when at least a second type is provided, hello() should use it.
The code above complains that there should be at least two template arguments, because there are "two" ground cases instead of one.
Maybe someone else can do better, but I see only two ways
Recursion inheritance
You can define MyClass recursively as follows
// recursive case
template <typename T, typename ... Ts>
struct MyClass : public MyClass<Ts...>
{
using MyClass<Ts...>::hello;
virtual void hello (const T&) = 0;
};
// ground case
template <typename T>
struct MyClass<T>
{ virtual void hello (const T&) = 0; };
or
variadic inheritance
You can define another class/struct, say MyHello, that declare a
single hello() method, and variadic inherit it from MyClass.
template <typename T>
struct MyHello
{ virtual void hello (const T&) = 0; };
template <typename ... Ts>
struct MyClass : public MyHello<Ts>...
{ };
The recursive example is compatible with type collision (that is: works also when a type is present more time in the list of template arguments MyClass; by example MyClass<int, double, int>).
The variadic inheritance case, unfortunately, isn't.
The following is a full compiling example
#if 1
// recursive case
template <typename T, typename ... Ts>
struct MyClass : public MyClass<Ts...>
{
using MyClass<Ts...>::hello;
virtual void hello (const T&) = 0;
};
// ground case
template <typename T>
struct MyClass<T>
{ virtual void hello (const T&) = 0; };
#else
template <typename T>
struct MyHello
{ virtual void hello (const T&) = 0; };
template <typename ... Ts>
struct MyClass : public MyHello<Ts>...
{ };
#endif
struct Derived : public MyClass<double, int>
{
inline void hello (const double&) override { }
inline void hello (const int&) override { }
};
int main()
{
Derived d;
d.hello(1.0);
d.hello(2);
}
-- EDIT --
The OP asks
how about a more complicated case where MyClass has more than one method and I always need to have one template argument (see edited question)?
From your question I don't understand what do you exactly want.
But supposing you want a pure virtual method, say goodmorning() that receive a MandT (the mandatory type), a pure virtual method hello() for every type following MandT or an hello() without arguments when the list after MandT is empty.
A possible solution is the following
// declaration and groundcase with only mandatory type (other cases
// intecepted by specializations)
template <typename MandT, typename ...>
struct MyClass
{
virtual void hello () = 0;
virtual ~MyClass () {}
virtual char * goodmorning (MandT const &) = 0;
};
// groundcase with a single optional type
template <typename MandT, typename OptT>
struct MyClass<MandT, OptT>
{
virtual void hello (OptT const &) = 0;
virtual ~MyClass () {}
virtual char * goodmorning (MandT const &) = 0;
};
// recursive case
template <typename MandT, typename OptT, typename ... MoreOptTs>
struct MyClass<MandT, OptT, MoreOptTs...>
: public MyClass<MandT, MoreOptTs...>
{
using MyClass<MandT, MoreOptTs...>::hello;
virtual void hello (OptT const &) = 0;
virtual ~MyClass () {}
};
Here the recursion is a little more complicated than before.
In case you instantiate a MyClass with only the mandatory type (by example: MyClass<char>) the main version ("groundcase with only mandatory type") is selected because the two specialization doesn't match (no first optional type).
In case you instantiate a Myclass with one optional type (say MyClass<char, double>) the specialization "groundcase with a single optional type" is selected because is the most specialized version.
In case you instantiate a MyClass with two or more optional type (say MyClass<char, double, int> start recursion (last specialization) until remain an single optional type (so the "groundcase with a single optional type" is selected).
Observe that I've placed the goodmorning() in both ground cases, because you don't need to define it recursively.
The following is a full compiling example
// declaration and groundcase with only mandatory type (other cases
// intecepted by specializations)
template <typename MandT, typename ...>
struct MyClass
{
virtual void hello () = 0;
virtual ~MyClass () {}
virtual char * goodmorning (MandT const &) = 0;
};
// groundcase with a single optional type
template <typename MandT, typename OptT>
struct MyClass<MandT, OptT>
{
virtual void hello (OptT const &) = 0;
virtual ~MyClass () {}
virtual char * goodmorning (MandT const &) = 0;
};
// recursive case
template <typename MandT, typename OptT, typename ... MoreOptTs>
struct MyClass<MandT, OptT, MoreOptTs...>
: public MyClass<MandT, MoreOptTs...>
{
using MyClass<MandT, MoreOptTs...>::hello;
virtual void hello (OptT const &) = 0;
virtual ~MyClass () {}
};
struct Derived0 : public MyClass<char>
{
void hello () override { }
char * goodmorning (char const &) override
{ return nullptr; }
};
struct Derived1 : public MyClass<char, double>
{
void hello (double const &) override { }
char * goodmorning (char const &) override
{ return nullptr; }
};
struct Derived2 : public MyClass<char, double, int>
{
void hello (double const &) override { }
void hello (int const &) override { }
char * goodmorning (char const &) override
{ return nullptr; }
};
int main()
{
Derived0 d0;
Derived1 d1;
Derived2 d2;
d0.hello();
d0.goodmorning('a');
d1.hello(1.2);
d1.goodmorning('b');
d2.hello(3.4);
d2.hello(5);
d2.goodmorning('c');
}

C++ class template constructor making decision based on type

I found a similar question here but it does not specifically answer my question. I have a simple class template that only takes one parameter. It does not store any member variables and has no methods other than a simple constructor. Based on the type passed in I need to branch my logic within the constructor. A simple version shell of the class would look like this as to what I'm trying to do. The class will take Type t do some processing and will store the results into an std::string by reference.
template<class Type>
struct Test {
Test( Type t, std::string& str ) {
static_assert( std::is_arithmetic<Type>::value, "Arithmetic type required." );
if ( std::is_arithmetic<Type>::value ) { // check if type is arithmetic
// some variables here
// Note: I do not want to static_assert here if type is integral.
// If assert fails the else will not be executed.
if ( std::is_integral<type>::value ) {
// some code for integral types
} else {
// some other code for arithmetic non integral types (floating point types)
}
str = // some code.
} else {
// possibly throw some exception
}
}
};
Is this an adequate way to resolve branch decisions based on data type? Or is there a more desirable-efficient way of doing this?
I could have a default constructor with a few member variables and overload 2 or 3 functions
I could do partial specialization of the class (not preferred).
I could just eliminate the "class-struct" altogether and do this as a function template, however, I would prefer to instantiate objects of this type.
What about mixing tag dispatching and delegating constructors?
I mean... something like
template <typename Type>
struct Test
{
Test (Type t, std::string & str, std::true_type const &,
std::true_type const &)
{ str = "case arithmetic and integral"; }
Test (Type t, std::string & str, std::true_type const &,
std::false_type const &)
{ str = "case arithmetic but not integral"; }
Test (Type t, std::string & str, std::false_type const &, ...)
{ str = "case not arithmetic"; /* + throw ? */ }
Test (Type t, std::string & str)
: Test(t, str, std::is_arithmetic<Type>{}, std::is_integral<Type>{})
{ }
};
int main ()
{
std::string str;
Test<int>(0, str);
std::cout << str << std::endl;
Test<float>(0.0f, str);
std::cout << str << std::endl;
Test<std::string>("zero", str);
std::cout << str << std::endl;
}
If the common code is relevant, you can define a single delegating constructor for the arithmetic types and use tag dispatching with a member called in the body.
That is
template <typename Type>
struct Test
{
void func (std::string & str, std::true_type const &)
{ str = "case integral"; }
void func (std::string & str, std::false_type const &)
{ str = "case not integral"; }
Test (Type t, std::string & str, std::true_type const &)
{
// variable definition and common code
func(str, /* other variables */ std::is_integral<Type>{});
// other common code
str += " plus common";
}
Test (Type t, std::string & str, std::false_type const &)
{ str = "case not arithmetic"; /* + throw ? */ }
Test (Type t, std::string & str)
: Test(t, str, std::is_arithmetic<Type>{})
{ }
};

Persistent expression templates with unique_ptr and matrices

I want to use expression templates to create a tree of objects that persists across statement. Building the tree initially involves some computations with the Eigen linear algebra library. The persistent expression template will have additional methods to compute other quantities by traversing the tree in different ways (but I'm not there yet).
To avoid problems with temporaries going out of scope, subexpression objects are managed through std::unique_ptr. As the expression tree is built, the pointers should be propagated upwards so that holding the pointer for the root object ensures all objects are kept alive. The situation is complicated by the fact that Eigen creates expression templates holding references to temporaries that go out of scope at the end of the statement, so all Eigen expressions must be evaluated while the tree is being constructed.
Below is a scaled-down implementation that seems to work when the val type is an object holding an integer, but with the Matrix type it crashes while constructing the output_xpr object. The reason for the crash seems to be that Eigen's matrix product expression template (Eigen::GeneralProduct) gets corrupted before it is used. However, none of the destructors either of my own expression objects or of GeneralProduct seems to get called before the crash happens, and valgrind doesn't detect any invalid memory accesses.
Any help will be much appreciated! I'd also appreciate comments on my use of move constructors together with static inheritance, maybe the problem is there somewhere.
#include <iostream>
#include <memory>
#include <Eigen/Core>
typedef Eigen::MatrixXi val;
// expression_ptr and derived_ptr: contain unique pointers
// to the actual expression objects
template<class Derived>
struct expression_ptr {
Derived &&transfer_cast() && {
return std::move(static_cast<Derived &&>(*this));
}
};
template<class A>
struct derived_ptr : public expression_ptr<derived_ptr<A>> {
derived_ptr(std::unique_ptr<A> &&p) : ptr_(std::move(p)) {}
derived_ptr(derived_ptr<A> &&o) : ptr_(std::move(o.ptr_)) {}
auto operator()() const {
return (*ptr_)();
}
private:
std::unique_ptr<A> ptr_;
};
// value_xpr, product_xpr and output_xpr: expression templates
// doing the actual work
template<class A>
struct value_xpr {
value_xpr(const A &v) : value_(v) {}
const A &operator()() const {
return value_;
}
private:
const A &value_;
};
template<class A,class B>
struct product_xpr {
product_xpr(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) :
a_(std::move(a).transfer_cast()), b_(std::move(b).transfer_cast()) {
}
auto operator()() const {
return a_() * b_();
}
private:
derived_ptr<A> a_;
derived_ptr<B> b_;
};
// Top-level expression with a matrix to hold the completely
// evaluated output of the Eigen calculations
template<class A>
struct output_xpr {
output_xpr(expression_ptr<derived_ptr<A>> &&a) :
a_(std::move(a).transfer_cast()), result_(a_()) {}
const val &operator()() const {
return result_;
}
private:
derived_ptr<A> a_;
val result_;
};
// helper functions to create the expressions
template<class A>
derived_ptr<value_xpr<A>> input(const A &a) {
return derived_ptr<value_xpr<A>>(std::make_unique<value_xpr<A>>(a));
}
template<class A,class B>
derived_ptr<product_xpr<A,B>> operator*(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) {
return derived_ptr<product_xpr<A,B>>(std::make_unique<product_xpr<A,B>>(std::move(a).transfer_cast(), std::move(b).transfer_cast()));
}
template<class A>
derived_ptr<output_xpr<A>> eval(expression_ptr<derived_ptr<A>> &&a) {
return derived_ptr<output_xpr<A>>(std::make_unique<output_xpr<A>>(std::move(a).transfer_cast()));
}
int main() {
Eigen::MatrixXi mat(2, 2);
mat << 1, 1, 0, 1;
val one(mat), two(mat);
auto xpr = eval(input(one) * input(two));
std::cout << xpr() << std::endl;
return 0;
}
Your problem appears to be that you are using someone else's expression templates, and storing the result in an auto.
(This happens in product_xpr<A>::operator(), where you call *, which if I read it right, is an Eigen multiplication that uses expression templates).
Expression templates are often designed to presume the entire expression will occur on a single line, and it will end with a sink type (like a matrix) that causes the expression template to be evaluated.
In your case, you have a*b expression template, which is then used to construct an expression template return value, which you later evaluate. The lifetime of temporaries passed to * in a*b are going to be over by the time you reach the sink type (matrix), which violates what the expression templates expect.
I am struggling to come up with a solution to ensure that all temporary objects have their lifetime extended. One thought I had was some kind of continuation passing style, where instead of calling:
Matrix m = (a*b);
you do
auto x = { do (a*b) pass that to (cast to matrix) }
replace
auto operator()() const {
return a_() * b_();
}
with
template<class F>
auto operator()(F&& f) const {
return std::forward<F>(f)(a_() * b_());
}
where the "next step' is passed to each sub-expression. This gets trickier with binary expressions, in that you have to ensure that the evaluation of the first expression calls code that causes the second sub expression to be evaluated, and then the two expressions are combined, all in the same long recursive call stack.
I am not proficient enough in continuation passing style to untangle this knot completely, but it is somewhat popular in the functional programming world.
Another approach would be to flatten your tree into a tuple of optionals, then construct each optional in the tree using a fancy operator(), and manually hook up the arguments that way. Basically do manual memory management of the intermediate values. This will work if the Eigen expression templates are either move-aware or do not have any self-pointers, so that moving at the point of construction doesn't break things. Writing that would be challenging.
Continuation passing style, suggested by Yakk, solves the problem and isn't too insane (not more insane than template metaprogramming in general anyhow). The double lambda evaluation for the arguments of binary expressions can be tucked away in a helper function, see binary_cont in the code below. For reference, and since it's not entirely trivial, I'm posting the fixed code here.
If somebody understands why I had to put a const qualifier on the F type in binary_cont, please let me know.
#include <iostream>
#include <memory>
#include <Eigen/Core>
typedef Eigen::MatrixXi val;
// expression_ptr and derived_ptr: contain unique pointers
// to the actual expression objects
template<class Derived>
struct expression_ptr {
Derived &&transfer_cast() && {
return std::move(static_cast<Derived &&>(*this));
}
};
template<class A>
struct derived_ptr : public expression_ptr<derived_ptr<A>> {
derived_ptr(std::unique_ptr<A> &&p) : ptr_(std::move(p)) {}
derived_ptr(derived_ptr<A> &&o) = default;
auto operator()() const {
return (*ptr_)();
}
template<class F>
auto operator()(F &&f) const {
return (*ptr_)(std::forward<F>(f));
}
private:
std::unique_ptr<A> ptr_;
};
template<class A,class B,class F>
auto binary_cont(const derived_ptr<A> &a_, const derived_ptr<B> &b_, const F &&f) {
return a_([&b_, f = std::forward<const F>(f)] (auto &&a) {
return b_([a = std::forward<decltype(a)>(a), f = std::forward<const F>(f)] (auto &&b) {
return std::forward<const F>(f)(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b));
});
});
}
// value_xpr, product_xpr and output_xpr: expression templates
// doing the actual work
template<class A>
struct value_xpr {
value_xpr(const A &v) : value_(v) {}
template<class F>
auto operator()(F &&f) const {
return std::forward<F>(f)(value_);
}
private:
const A &value_;
};
template<class A,class B>
struct product_xpr {
product_xpr(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) :
a_(std::move(a).transfer_cast()), b_(std::move(b).transfer_cast()) {
}
template<class F>
auto operator()(F &&f) const {
return binary_cont(a_, b_,
[f = std::forward<F>(f)] (auto &&a, auto &&b) {
return f(std::forward<decltype(a)>(a) * std::forward<decltype(b)>(b));
});
}
private:
derived_ptr<A> a_;
derived_ptr<B> b_;
};
template<class A>
struct output_xpr {
output_xpr(expression_ptr<derived_ptr<A>> &&a) :
a_(std::move(a).transfer_cast()) {
a_([this] (auto &&x) { this->result_ = x; });
}
const val &operator()() const {
return result_;
}
private:
derived_ptr<A> a_;
val result_;
};
// helper functions to create the expressions
template<class A>
derived_ptr<value_xpr<A>> input(const A &a) {
return derived_ptr<value_xpr<A>>(std::make_unique<value_xpr<A>>(a));
}
template<class A,class B>
derived_ptr<product_xpr<A,B>> operator*(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) {
return derived_ptr<product_xpr<A,B>>(std::make_unique<product_xpr<A,B>>(std::move(a).transfer_cast(), std::move(b).transfer_cast()));
}
template<class A>
derived_ptr<output_xpr<A>> eval(expression_ptr<derived_ptr<A>> &&a) {
return derived_ptr<output_xpr<A>>(std::make_unique<output_xpr<A>>(std::move(a).transfer_cast()));
}
int main() {
Eigen::MatrixXi mat(2, 2);
mat << 1, 1, 0, 1;
val one(mat), two(mat), three(mat);
auto xpr = eval(input(one) * input(two) * input(one) * input(two));
std::cout << xpr() << std::endl;
return 0;
}

Forbid copy-construction of base class

I'm wanting to quickly implement what some call an "owner pointer", that is, a smart pointer ensuring unique ownership semantics, while providing "observer" pointers that don't keep the object alive, but can test whether it is.
The most straightforward way I'm trying to do it is to subclass std::shared_ptr, and disable its copy-construction so that no other pointer can actually share the object.
This is what I have for now :
#include <memory>
#include <iostream>
template <class T>
struct owner_ptr : public std::shared_ptr<T> {
// Import constructors
using std::shared_ptr<T>::shared_ptr;
// Disable copy-construction
owner_ptr(owner_ptr<T> const&) = delete;
// Failed attempt at forbidding what comes next
operator std::shared_ptr<T> const&() = delete;
};
struct Foo {
Foo() {
std::cout << "Hello Foo\n";
}
~Foo() {
std::cout << "G'bye Foo\n";
}
void talk() {
std::cout << "I'm talkin'\n";
}
};
owner_ptr<Foo> fooPtr(new Foo);
int main(int, char**) {
// This should not compile, but it does.
std::shared_ptr<Foo> sptr = fooPtr;
// Simple tests
fooPtr->talk();
(*fooPtr).talk();
// Confirmation that two pointers are sharing the object (it prints "2").
std::cout << sptr.use_count() << '\n';
}
I've been pulling my hair on this one. How do I forbid the copy-construction of a std::shared_ptr from my owner_ptr ? I'm not fond of inheriting privately and then importing everything from std::shared_ptr...
I don't think subclassing std::shared_ptr is the way to go. If you really wanted to do it properly I think you should implement it yourself including all the reference counting. Implementing a smart pointer is not actually that hard.
However, in most cases, if you just want something that meets your needs use composition.
I was curious about what you were trying to do, I'm not convinced it is a good idea but I had a go at implementing a OwnerPointer and ObserverPointer pair using composition:
#include <memory>
#include <iostream>
struct Foo {
Foo() {std::cout << "Hello Foo\n"; }
~Foo() { std::cout << "G'bye Foo\n"; }
void talk() { std::cout << "I'm talkin'\n"; }
};
template <class T>
class ObserverPointer; // Forward declaration.
template<class T>
class OwnerPointer; // Forward declaration.
// RAII object that can be obtained from ObserverPointer
// that ensures the ObserverPointer does not expire.
// Only operation is to test validity.
template <class T>
class ObserverLock {
friend ObserverPointer<T>;
private:
std::shared_ptr<T> impl_;
ObserverLock(const std::weak_ptr<T>& in) : impl_(in.lock()) {}
public:
// Movable.
ObserverLock(ObserverLock&&) = default;
ObserverLock& operator=(ObserverLock&&) = default;
// Not copyable.
ObserverLock& operator=(const ObserverLock&) = delete;
ObserverLock(const ObserverLock&) = delete;
// Test validity.
explicit operator bool() const noexcept { return impl_ != nullptr;}
};
template <class T>
class ObserverPointer {
private:
std::weak_ptr<T> impl_;
T* raw_;
public:
ObserverPointer(const OwnerPointer<T>& own) noexcept : impl_(own.impl_), raw_(own.get()) {}
T* get() const { return raw_; }
T* operator->() const { return raw_; }
T& operator*() const { return *raw_; }
ObserverPointer() : impl_(), raw_(nullptr) { }
ObserverPointer(const ObserverPointer& in) = default;
ObserverPointer(ObserverPointer&& in) = default;
ObserverPointer& operator=(const ObserverPointer& in) = default;
ObserverPointer& operator=(ObserverPointer&& in) = default;
bool expired() { return impl_.expired(); }
ObserverLock<T> lock() { return ObserverLock<T>(impl_); }
};
template <class T>
struct OwnerPointer {
friend ObserverPointer<T>;
private:
std::shared_ptr<T> impl_;
public:
// Constructors
explicit OwnerPointer(T* in) : impl_(in) {}
template<class Deleter>
OwnerPointer(std::unique_ptr<T, Deleter>&& in) : impl_(std::move(in)) { }
OwnerPointer(std::shared_ptr<T>&& in) noexcept : impl_(std::move(in)) { }
OwnerPointer(OwnerPointer<T>&&) noexcept = default;
OwnerPointer(OwnerPointer<T> const&) = delete;
// Assignment operators
OwnerPointer& operator=(OwnerPointer<T> const&) = delete;
OwnerPointer& operator=(OwnerPointer<T>&&) = default;
T* get() const { return impl_.get(); }
T* operator->() const { return impl_.get(); }
T& operator*() const { return *impl_; }
explicit operator ObserverPointer<T>() const noexcept { return ObserverPointer<T>(impl_);}
explicit operator bool() const noexcept { return impl_;}
};
// Convenience function equivalent to make_shared
template <class T, class... Args>
OwnerPointer<T> make_owner(Args && ...args) {
return OwnerPointer<T>(new T(std::forward<Args>(args)...));
}
int main() {
auto owner = make_owner<Foo>();
ObserverPointer<Foo> observer = owner;
auto lock = observer.lock();
if (lock)
observer->talk();
}
Live demo.
It probably needs some work and it doesn't offer the full feature set of std::shared_ptr & std::weak_ptr but then in most cases it won't need to, just create what you need.
I've stretched the definition of "unique ownership" by offering an RAII ObserverLock object that can only be used to keep the ObserverPointer alive. Technically it "owns" the pointer but it is very restricted in what it can do and you can't create more than one "OwnerPointer".

Resources