class A {};
class B{
unique_ptr<A> upA;
public:
B() : upA(make_unique<A>()) {}
const A* get() const{
return upA.get();
}
};
How do you return a const reference instead of a const ptr?
Use unary operator* - the deference operator:
const A& get_ref() const{
return *upA;
}
Related
First i realize unique_ptr by myself:
namespace mcj {
template <typename CallbackT>
class unique_ptr {
public:
unique_ptr(CallbackT* ptr = nullptr) : ptr_(ptr) {}
template <
typename CallbackT1,
typename = typename std::enable_if<
std::is_convertible<CallbackT1*, CallbackT*>::value>::type>
unique_ptr(unique_ptr<CallbackT1>&& ptr) {
ptr_ = ptr.release();
}
unique_ptr(unique_ptr<CallbackT>&& ptr) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
ptr_ = ptr.release();
}
template <
typename CallbackT1,
typename = typename std::enable_if<
std::is_convertible<CallbackT1*, CallbackT*>::value>::type>
unique_ptr<CallbackT>& operator=(unique_ptr<CallbackT1>&& ptr) {
ptr_ = ptr.release();
}
unique_ptr<CallbackT>& operator=(unique_ptr<CallbackT>&& ptr) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
ptr_ = ptr.release();
return *this;
}
unique_ptr(const unique_ptr<CallbackT>& other) = delete;
unique_ptr<CallbackT>& operator=(const unique_ptr<CallbackT>& other) = delete;
~unique_ptr() {
delete ptr_;
ptr_ = nullptr;
}
CallbackT& operator*() { return *ptr_; }
CallbackT* operator->() { return ptr_; }
CallbackT* get() const { return ptr_; };
CallbackT* release() {
if (ptr_) {
CallbackT* temp = ptr_;
ptr_ = nullptr;
return temp;
}
return ptr_;
}
private:
CallbackT* ptr_;
};
} // namespace mcj
namespace mcj {
template <typename CallbackT, typename ClosureT>
inline mcj::unique_ptr<CallbackT> make_unique(ClosureT&& closure) {
return mcj::unique_ptr<CallbackT>(new CallbackT(std::forward<ClosureT>(closure)));
}
then i test my unique_ptr like these and successfully!
class A {
public:
A() {}
A(A* ptr) {
this->a = ptr->a;
this->b = ptr->b;
}
A(const A& ptr) {
this->a = ptr.a;
this->b = ptr.b;
}
A(A&& ptr) {
a = ptr.a;
b = ptr.b;
}
void GetA() { std::cout << "a:" << a << std::endl; }
int a = 0;
};
auto s1 = std::make_unique<A>();
s1->GetA();
mcj::unique_ptr<A> a(new A());
a->GetA();
mcj::unique_ptr<A> b(std::move(a));
b->GetA();
mcj::unique_ptr<A> c;
c = std::move(b);
c->GetA();
above exapmles shows that my unique_ptr has overrided operator-> successfully!While when i want to try more complex class, it failed! Please look following code
namespace mcj {
class AppleCallback {
public:
virtual ~AppleCallback() = default;
virtual void OnAppleComplete(int err) = 0;
};
namespace callback_impl {
template <typename CallbackT, typename ClosureT>
class ClosureCallback : public CallbackT {
public:
explicit ClosureCallback(ClosureT&& closure)
: closure_(std::forward<ClosureT>(closure)) {}
protected:
typename std::remove_reference<ClosureT>::type closure_;
};
template <typename ClosureT>
class AppleCallbackImpl : public ClosureCallback<mcj::AppleCallback, ClosureT> {
public:
explicit AppleCallbackImpl(ClosureT&& closure)
: ClosureCallback<AppleCallback, ClosureT>(
std::forward<ClosureT>(closure)) {}
void OnAppleComplete(int err) override {
this->closure_(err);
}
};
} // namespace callback_impl
} // namespace mcj
namespace mcj {
template <typename CallbackT,
typename ClosureT,
typename std::enable_if<
std::is_same<CallbackT, AppleCallback>::value>::type* = nullptr>
mcj::unique_ptr<CallbackT> ToUniqueCallback(ClosureT&& closure) {
return mcj::make_unique<callback_impl::AppleCallbackImpl<ClosureT>>(
std::forward<ClosureT>(closure));
}
} // namespace mcj
namespace mcj {
template <typename CallbackT>
class MoveOnlyCallback {
using MyType = MoveOnlyCallback<CallbackT>;
mcj::unique_ptr<CallbackT> callback_;
public:
template <typename ClosureT>
MoveOnlyCallback(ClosureT&& closure)
: callback_(
ToUniqueCallback<CallbackT>(std::forward<ClosureT>(closure))) {
std::cout << "move constructor\n" << std::endl;
}
MoveOnlyCallback(std::unique_ptr<CallbackT> callback)
: callback_(std::move(callback)) {}
MoveOnlyCallback() = default;
MoveOnlyCallback(const MyType&) = delete;
MoveOnlyCallback(MyType&&) noexcept = default;
MyType& operator=(const MyType&) = delete;
MyType& operator=(MyType&&) noexcept = default;
CallbackT* operator->() const { return callback_.get(); }
explicit operator bool() const noexcept { return callback_.operator bool(); }
CallbackT* Get() const noexcept { return callback_.get(); };
CallbackT* Release() noexcept { return callback_.release(); }
mcj::unique_ptr<CallbackT> ReleaseUnique() noexcept {
return std::move(callback_);
}
};
class Apple : public Fruit {
public:
virtual ~Apple() = default;
void Name() override { std::cout << "I am apple \n" << std::endl; }
void Eat(MoveOnlyCallback<AppleCallback> callback) {
callback->OnAppleComplete(0);
// InvokeCallback(callback.Get(), 0);
}
};
} // namespace mcj
when i call function "Eat" of class "Apple" like this, it occurs error about operation-> of my unique_ptr, and if i replace my unique_ptr by std::unique_ptr, it is ok!
Apple* apple = new Apple();
apple->Eat(ToUniqueCallback<AppleCallback>(
[](int err) { std::cout << "eat callback" << std::endl; }));
here is error message!
/Users/chaojie.mo/Documents/test/src/callback_utils.h:138:5: error:
type 'mcj::unique_ptrmcj::AppleCallback' does not provide a call
operator
this->closure_(err);
^~~~~~~~~~~~~~ /Users/chaojie.mo/Documents/test/src/callback_utils.h:134:12: note: in
instantiation of member function
'mcj::callback_impl::AppleCallbackImplmcj::unique_ptr<mcj::AppleCallback>::OnAppleComplete'
requested here explicit AppleCallbackImpl(ClosureT&& closure)
^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:81:41: note: in
instantiation of member function
'mcj::callback_impl::AppleCallbackImplmcj::unique_ptr<mcj::AppleCallback>::AppleCallbackImpl'
requested here return mcj::unique_ptr(new
CallbackT(std::forward(closure)));
^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:153:15: note: in
instantiation of function template specialization
'mcj::make_uniquemcj::callback_impl::AppleCallbackImpl<mcj::unique_ptr<mcj::AppleCallback>,
mcj::unique_ptrmcj::AppleCallback>' requested here return
mcj::make_unique<callback_impl::AppleCallbackImpl>(
^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:168:13: note: in
instantiation of function template specialization
'mcj::ToUniqueCallback<mcj::AppleCallback,
mcj::unique_ptrmcj::AppleCallback, nullptr>' requested here
ToUniqueCallback(std::forward(closure))) {
^ /Users/chaojie.mo/Documents/test/test/main.cpp:77:14: note: in instantiation of function template specialization
'mcj::MoveOnlyCallbackmcj::AppleCallback::MoveOnlyCallbackmcj::unique_ptr<mcj::AppleCallback>'
requested here apple->Eat(ToUniqueCallback(
MoveOnlyCallback has a constructor taking std::unique_ptr, but doesn't have one taking mcj::unique_ptr. Constructing from the latter ends up in the generic constructor template <typename ClosureT> MoveOnlyCallback(ClosureT&& closure). As a result you end up with double indirection, msj::unique_ptr<msj::unique_ptr<CallbackT>>
I'm trying to get the multi_index_t code from the second answer here answered by davidhigh to work with C++11. C++11 does not support auto& type returns.
I converted the return types for the class, but I don't understand how/if it's possible to support the helper function multi_index() without using C++14.
The code:
#include<array>
template<int dim>
struct multi_index_t
{
std::array<int, dim> size_array;
template<typename ... Args>
multi_index_t(Args&& ... args) : size_array(std::forward<Args>(args) ...) {}
struct iterator
{
struct sentinel_t {};
std::array<int, dim> index_array = {};
std::array<int, dim> const& size_array;
bool _end = false;
iterator(std::array<int, dim> const& size_array) : size_array(size_array) {}
iterator& operator++()
{
for (int i = 0;i < dim;++i)
{
if (index_array[i] < size_array[i] - 1)
{
++index_array[i];
for (int j = 0;j < i;++j) { index_array[j] = 0; }
return *this;
}
}
_end = true;
return *this;
}
std::array<int, dim>& operator*() { return index_array; }
bool operator!=(sentinel_t) const { return !_end; }
};
iterator begin() const { return iterator{ size_array }; }
iterator end() const { return typename iterator::sentinel_t{}; }
};
template<typename ... index_t>
auto multi_index(index_t&& ... index) // <-- this doesn't compile
{
static constexpr int size = sizeof ... (index_t);
auto ar = std::array<int, size>{std::forward<index_t>(index) ...};
return multi_index_t<size>(ar);
}
According to this answer, you can't recursively expand the variadic function template via decltype(). Any ideas?
C++11 does not support auto& type returns.
So you can simply explicit the types.
For multi_index() you have that return a multi_index_t<size>, where size is sizeof...(index_t), so you can write
template<typename ... index_t>
multi_index_t<sizeof...(index_t)> multi_index(index_t&& ... index)
According to this answer, you can't recursively expand the variadic function template via decltype.
Correct, but I don't see recursion in your multi_index() function, so I don't see how apply recursion over decltype().
If you really want (but why?), you can explicit the returning type through decltype() as follows
template<typename ... index_t>
auto multi_index(index_t&& ... index)
-> decltype( multi_index_t<sizeof...(index_t)>
{ std::array<int, sizeof...(index_t)>
{{ std::forward<index_t>(index) ... }} } )
but I don't see a reason to do this instead of simply explicit multi_index_t<sizeof...(index_t)>
I have the following scenario:
struct AP;
struct B
{
B() : m(2) {}
int m;
};
struct A : private B
{
A() : B(), n(1) {}
private:
int n;
friend AP;
};
struct AP
{
AP(A& a) : a_(a) {}
template<typename T>
struct A_B {
using type = typename std::enable_if< std::is_base_of< typename std::remove_reference<T>::type,
A >::value,
T >::type;
};
template<typename T>
operator typename A_B<T>::type()
{
return static_cast<T>(a_);
}
template<typename T>
typename A_B<T>::type get()
{
return static_cast<T>(a_);
}
int& n() { return a_.n; }
private:
A& a_;
};
int main()
{
A a;
AP ap(a);
ap.n() = 7;
const B& b = ap.get<const B&>();
//const B& b = ap; candidate template ignored: couldn't infer template argument 'T'
//auto b = static_cast<const B&>(ap); candidate template ignored: couldn't infer template argument 'T'
std::cout<<b.m;
}
The commented lines wouldn't compile. Clang++ notes that "candidate template ignored: couldn't infer template argument 'T'"
Why am I not able to get a reference to A's base with the cast operator?
I think the code would look much nicer that way.
The answer that you posted works, but is overkill unless you really want a static_assert message.
Classic templating works just fine in this instance because A is already convertible to B:
struct AP
{
AP(A& a) : a_(a) {}
template<typename T>
operator T()
{
return a_;
}
template<typename T>
T get()
{
return a_;
}
int& n() { return a_.n; }
private:
A& a_;
};
Demo
I found the answer here: http://www.mersenneforum.org/showthread.php?t=18076
This is the key: "when you want the compiler to deduce argument types, those types must not be dependent types"
With this it compiles:
template<typename T>
operator T()
{
static_assert(std::is_base_of< typename std::remove_reference<T>::type,A >::value,
"You may cast AP only to A's base classes.");
return static_cast<T>(a_);
}
My aim is to learn how to write a custom iterator from scratch. I have written the following iterator:
#include <iterator>
template<class D>
class SpanIterator final : public std::iterator<std::random_access_iterator_tag, D>
{
private:
D* _data;
public:
explicit SpanIterator(D* data) :
_data{ data }
{
}
SpanIterator(const SpanIterator& itertator) = default;
SpanIterator& operator=(const SpanIterator& iterator) = default;
SpanIterator& operator=(D* data)
{
_data = data;
return *this;
}
operator bool() const
{
return _data != nullptr;
}
bool operator==(const SpanIterator& itertator) const
{
return _data == itertator._data;
}
bool operator!=(const SpanIterator& itertator) const
{
return _data != itertator._data;
}
SpanIterator& operator+=(const std::ptrdiff_t& movement)
{
_data += movement;
return *this;
}
SpanIterator& operator-=(const std::ptrdiff_t& movement)
{
_data -= movement;
return *this;
}
SpanIterator& operator++()
{
++_data;
return *this;
}
SpanIterator& operator--()
{
--_data;
return *this;
}
SpanIterator operator++(int)
{
auto temp = *this;
++_data;
return temp;
}
SpanIterator operator--(int)
{
auto temp = *this;
--_data;
return temp;
}
SpanIterator operator+(const std::ptrdiff_t& movement)
{
auto oldPtr = _data;
_data += movement;
auto temp = *this;
_data = oldPtr;
return temp;
}
SpanIterator operator-(const std::ptrdiff_t& movement)
{
auto oldPtr = _data;
_data -= movement;
auto temp = *this;
_data = oldPtr;
return temp;
}
D& operator*()
{
return *_data;
}
const D& operator*() const
{
return *_data;
}
D& operator->()
{
return _data;
}
};
Which I am testing like so:
#include <iostream>
#include <array>
int main()
{
std::array<double, 3> values = { 1, 2, 1 };
SpanIterator<double> begin{ values.data() };
SpanIterator<double> end{ values.data() + values.size() };
std::sort(begin, end);
return EXIT_SUCCESS;
}
However it fails to compile, giving the following errors:
Error C2666 'SpanIterator::operator -': 2 overloads
Error C2780 'void std::_Sort_unchecked1(_RanIt,_RanIt,_Diff,_Pr &)':
expects 4 arguments - 3 provided
If I remove SpanIterator operator-(const std::ptrdiff_t& movement) I get different errors:
'void std::_Guess_median_unchecked(_RanIt,_RanIt,_RanIt,_Pr &)':
could not deduce template argument for '_RanIt' from 'int'
'_Guess_median_unchecked': no matching overloaded function found
Error C2100 illegal indirection
You're missing operators to support the following operations (where a and b are values of your iterator type SpanIterator<...>):
b - a
a < b (and the remaining comparisons, although most implementations of std::sort don't use them).
For example, you could provide the following member operator overloads:
std::ptrdiff_t operator-(SpanIterator const&) const;
bool operator<(SpanIterator const&) const;
// etc.
(Note that non-member overloads are often preferred: Operator overloading)
In addition, your operator bool should be explicit to avoid ambiguous overloads for the a + n, n + a and b - a operations (where n is a value of your difference type i.e. std::ptrdiff_t).
The find method of boost::splay_set that require only the key accepts an argument of type KeyValueCompare to compare objects with the key. To be able to use this, we need to supply two methods of the form:
struct KeyValCompare {
inline bool operator() (const std::int64_t key, const MyType& val) const {
//TODO:
}
inline bool operator() (const MyType& val, const std::int64_t key) const {
//TODO:
}
};
However there is no mention in the documentation about how to implement these. Any pointers?
Found a solution here:
http://boost.cowic.de/rc/pdf/intrusive.pdf
they should return true if key (or key from the value) of lhs is less than the key (or key from the value) of rhs.
I don't see why the comparator would be so complicated. The set just stores elements of MyType, so you need to define a strict weak total ordering on them:
struct Comparator {
bool operator()(MyType const& a, MyType const& b) const;
};
Indeed, the default comparer is std::less<MyType>
E.g. to sort
class MyType : public splay_set_base_hook<>
{
int int_;
public:
MyType(int i) : int_(i) {}
int getValue() const { return int_; }
};
By the value, after reversing the digits (e.g. "431" before "322" because 134<223):
struct CompareReversed {
bool operator()(MyType const& a, MyType const& b) const {
return reversed(a.getValue()) < reversed(b.getValue());
}
private:
static int reversed(int i)
{
auto s = std::to_string(i);
std::reverse(s.begin(), s.end());
return boost::lexical_cast<int>(s);
}
};
See it Live On Coliru:
#include <boost/intrusive/splay_set.hpp>
#include <boost/lexical_cast.hpp>
#include <vector>
#include <algorithm>
using namespace boost::intrusive;
class MyType : public splay_set_base_hook<>
{
int int_;
public:
MyType(int i) : int_(i)
{}
// default ordering
friend bool operator< (const MyType &a, const MyType &b) { return a.int_ < b.int_; }
friend bool operator> (const MyType &a, const MyType &b) { return a.int_ > b.int_; }
friend bool operator== (const MyType &a, const MyType &b) { return a.int_ == b.int_; }
int getValue() const { return int_; }
};
struct CompareReversed {
bool operator()(MyType const& a, MyType const& b) const {
return reversed(a.getValue()) < reversed(b.getValue());
}
private:
static int reversed(int i)
{
auto s = std::to_string(i);
std::reverse(s.begin(), s.end());
return boost::lexical_cast<int>(s);
}
};
#include <iostream>
int main()
{
//typedef splay_set<MyType, compare<std::less<MyType> > > Set;
typedef splay_set<MyType, compare<CompareReversed> > Set;
std::vector<MyType> v { 24, 42, 123, 321 };
Set set;
set.insert(v[0]);
set.insert(v[1]);
set.insert(v[2]);
set.insert(v[3]);
for (auto& el : set)
{
std::cout << el.getValue() << "\n";
}
std::cout << set.count(24) << "\n"; // 1
std::cout << set.count(25) << "\n"; // 0
std::cout << set.count(42) << "\n"; // 1
}
If you want to suppor mixed type comparisons, just supply the overloads, obviously:
struct CompareReversed {
bool operator()(MyType const& a, MyType const& b) const {
return reversed(a.getValue()) < reversed(b.getValue());
}
bool operator()(MyType const& a, int b) const {
return reversed(a.getValue()) < reversed(b);
}
bool operator()(int a, MyType const& b) const {
return reversed(a) < reversed(b.getValue());
}
// ...
};
Thanks sehe for the support.
That is exactly what I am doing there. But please have a look at following sample code which fails.
#include <boost/intrusive/splay_set.hpp>
#include <algorithm>
using namespace boost::intrusive;
class MyClass {
public:
MyClass(const std::int64_t& k)
: key(k) {
}
std::int64_t key;
splay_set_member_hook<> member_hook_;
friend bool operator <(const MyClass& lhs, const MyClass& rhs) {
return lhs.key < rhs.key;
}
friend bool operator >(const MyClass& lhs, const MyClass& rhs) {
return lhs.key > rhs.key;
}
friend bool operator ==(const MyClass& lhs, const MyClass& rhs) {
return lhs.key == rhs.key;
}
};
struct KeyValCompare {
inline bool operator()(const std::int64_t key, const MyClass& val) const {
return key < val.key;
}
inline bool operator()(const MyClass& val, const std::int64_t key) const {
return val.key < key;
}
};
typedef member_hook<MyClass, splay_set_member_hook<>, &MyClass::member_hook_> MemberOption;
typedef splay_set<MyClass, MemberOption, compare<std::greater<MyClass> > > MyClassObjectsType;
TEST(MyClass, test) {
MyClassObjectsType set;
set.insert(*new MyClass(10));
set.insert(*new MyClass(20));
set.insert(*new MyClass(100));
auto ite = set.find(100, KeyValCompare());
ASSERT_TRUE(ite != set.end()); // Fails here
}
If I use std::less instead of std::greater, it passes.
Figured it out:
The greater than operator must be change from:
friend bool operator >(const MyClass& lhs, const MyClass& rhs) {
return lhs.key > rhs.key;
}
to this:
friend bool operator >(const MyClass& lhs, const MyClass& rhs) {
return lhs.key < rhs.key;
}