make_pair like trick for noncopyable classes

461 views Asked by At

make_pair can create pairs without mentioning the types. I want to use the same trick for my class, but it inherits from boost::noncopyable, so this does not compile:

template<class Iter>
struct bit_writer : boost:noncopyable
{
    Iter iter;
    bit_writer(Iter iter)
    : iter(iter)
    {}
};

template<class Iter>
bit_writer<Iter> make_bit_writer(Iter iter)
{
    return bit_writer<Iter>(iter);
}
vector<char> vec;
auto w = make_bit_writer(vec);

Any alternative? I tried making make_bit_writer a friend, and then run out of ideas.

2

There are 2 answers

3
Flexo On BEST ANSWER

If you have C++11 you can do this using something like:

#include <functional>
#include <utility>
#include <type_traits>

struct noncopyable_but_still_moveable {
  noncopyable_but_still_moveable(const noncopyable_but_still_moveable&) = delete;
  noncopyable_but_still_moveable(noncopyable_but_still_moveable&&) = default;
  noncopyable_but_still_moveable() = default;
  noncopyable_but_still_moveable& operator=(const noncopyable_but_still_moveable&) = default;
  noncopyable_but_still_moveable& operator=(noncopyable_but_still_moveable&&) = default;
};

template <typename T>
struct test : noncopyable_but_still_moveable {
  test(T) {}
  // the rest is irrelevant 
};

template <typename T>
test<T> make_test(T&& val) {
  return test<typename std::remove_reference<T>::type>(std::forward<T>(val));
}

int main() {
  auto && w = make_test(0);
}

Note that I've replaced boost::noncopyable with a type that has a deleted copy constructor. This is the C++11 way of making something non-copyable and is needed because the boost class was also not moveable. Of course you could just put that inside the class itself and not inherit any more.

Without C++11 you'll want to use something like Boost move to emulate these semantics.

0
Puppy On

You will need C++11 and to update your class for move semantics. There is no other solution to the proposed problem.

class test {
public:
    test(test&&);
    // stuff
};
test make_test(...) {
    return test(...);
}
int main() {
    // Both valid:
    auto p = make_test(...);
    auto&& p2 = make_test(...);
}