operator== container iterator const and non-const - c++

I'm trying to have an eventmanager for the impossibly fast c++ delegate that was discussed in this article http://blog.coldflake.com/posts/C++-delegates-on-steroids/;
template <typename T, typename R, typename... Params>
class delegate<R (T::*)(Params...) const>
{
public:
typedef R (T::*func_type)(Params...) const;
delegate(func_type func, const T& callee)
: callee_(callee) , func_(func)
{}
R operator()(Params... args) const
{ return (callee_.*func_)(args...); }
bool operator==(const delegate& other) const
{ return (&callee_ == &other.callee_) && (func_ == other.func_); }
bool operator!= (const delegate& other) const
{ return !(*this == other); }
private:
const T& callee_;
func_type func_;
};
and one of the methods that I used;
using EventListenerDelegate = delegate<IEventDataPtr>;
using EventListenerList = std::list<EventListenerDelegate>;
bool EventManager::addListener(const EventListenerDelegate& eventDelegate, const EventType& type)
{
// this will find or create the entry
EventListenerList& eventListenerList = m_eventListeners[type];
for (auto it = eventListenerList.begin(); it != eventListenerList.end(); ++it)
{
if (eventDelegate == (*it))
{
std::cout <<"Attempting to double-register a delegate" << std::endl;
return false;
}
}
eventListenerList.push_back(eventDelegate);
return true;
}
The code failed to compile with gcc error message;
error: no match for 'operator==' (operand types are 'const EventListenerDelegate {aka const delegate<std::shared_ptr<IEventData> >}' and 'delegate<std::shared_ptr<IEventData> >')
if (eventDelegate == (*it))
^
What should I do to fix the error?
Thank you.
EDIT:
two other specialization templates in the code;
//specialization for free functions
template <typename R, typename... Params>
class delegate<R (*)(Params...)>
and;
//specialization for member functions
template <typename T, typename R, typename... Params>
class delegate<R (T::*)(Params...)>

Related

Why my UniqPtr objects are double in size compared to std::unique_ptr?

In real applications I should stick to the standard library facilities, for practice and understanding how those facilities work I should try to implement my own.
Here I've implemented a simulation of the smart pointer unique_ptr:
#include<iostream>
#include <memory>
template <typename T>
class DefDel
{
public:
template <typename U>
void operator()(U* p)const
{
std::cout << "freeing memory...\n";
delete p;
}
};
template <typename T>
class DefDel<T[]>
{
public:
template <typename U>
void operator()(U* p)const
{
std::cout << "freeing memory of an array of objects...\n";
delete[] p;
}
};
template <typename T, typename D = DefDel<T>>
class UniqPtr final
{
public:
UniqPtr(T* = nullptr, D = DefDel<T>{});
UniqPtr(UniqPtr const&) = delete;
UniqPtr(UniqPtr&&) noexcept;
UniqPtr& operator =(UniqPtr const&) = delete;
UniqPtr& operator =(UniqPtr&&) noexcept;
~UniqPtr();
T& operator*();
T const& operator*() const;
T* operator->();
T const* operator->() const;
operator bool() const;
private:
T* ptr_{nullptr};
D del_{};
};
template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(T* p, D del) :
ptr_(p),
del_(del)
{}
template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(UniqPtr&& rhs) noexcept :
ptr_(std::move(rhs.ptr_)),
del_(std::move(rhs.del_))
{
rhs.ptr_ = nullptr;
}
template <typename T, typename D>
UniqPtr<T, D>& UniqPtr<T, D>::operator = (UniqPtr&& rhs) noexcept
{
if(this != &rhs)
{
ptr_ = std::move(rhs.ptr_);
del_ = std::move(rhs.del_);
rhs.ptr_ = nullptr;
}
return *this;
}
template <typename T, typename D>
UniqPtr<T, D>::~UniqPtr()
{
del_(ptr_);
}
template <typename T, typename D>
T& UniqPtr<T, D>::operator*()
{
return *ptr_;
}
template <typename T, typename D>
T const& UniqPtr<T, D>::operator*() const
{
return *ptr_;
}
template <typename T, typename D>
T* UniqPtr<T, D>::operator->()
{
return ptr_;
}
template <typename T, typename D>
T const* UniqPtr<T, D>::operator->() const
{
return ptr_;
}
template <typename T, typename D>
UniqPtr<T, D>::operator bool() const
{
return ptr_;
}
// for array
template <typename T, typename D>
class UniqPtr<T[], D> final
{
public:
UniqPtr(T* = nullptr, D = DefDel<T[]>{});
UniqPtr(UniqPtr const&) = delete;
UniqPtr(UniqPtr&&) noexcept;
UniqPtr& operator =(UniqPtr const&) = delete;
UniqPtr& operator =(UniqPtr&&) noexcept;
~UniqPtr();
T& operator*();
T const& operator*() const;
T* operator->();
T const* operator->() const;
operator bool() const;
private:
T* ptr_{nullptr};
D del_{};
};
template <typename T, typename D>
UniqPtr<T[], D>::UniqPtr(T* p, D del) :
ptr_(p),
del_(del)
{}
template <typename T, typename D>
UniqPtr<T[], D>::UniqPtr(UniqPtr&& rhs) noexcept :
ptr_(std::move(rhs.ptr_)),
del_(std::move(rhs.del_))
{
rhs.ptr_ = nullptr;
}
template <typename T, typename D>
UniqPtr<T[], D>& UniqPtr<T[], D>::operator = (UniqPtr&& rhs) noexcept
{
if(this != &rhs)
{
ptr_ = std::move(rhs.ptr_);
del_ = std::move(rhs.del_);
rhs.ptr_ = nullptr;
}
return *this;
}
template <typename T, typename D>
UniqPtr<T[], D>::~UniqPtr()
{
del_(ptr_);
}
template <typename T, typename D>
T& UniqPtr<T[], D>::operator*()
{
return *ptr_;
}
template <typename T, typename D>
T const& UniqPtr<T[], D>::operator*() const
{
return *ptr_;
}
template <typename T, typename D>
T* UniqPtr<T[], D>::operator->()
{
return ptr_;
}
template <typename T, typename D>
T const* UniqPtr<T[], D>::operator->() const
{
return ptr_;
}
template <typename T, typename D>
UniqPtr<T[], D>::operator bool() const
{
return ptr_;
}
int main()
{
UniqPtr<int[]> upi(new int[3]{57});
std::cout << sizeof(upi) << '\n';
std::unique_ptr<int[], DefDel<int[]>> upi2(new int[3]{57});
std::cout << sizeof(upi2) << '\n';
}
Why the size of my UniqPtr objects are double in size as std::unique_ptr (even being initialized with the same values)?
Is that because of my class is storing a Del_ object as a member?
If that is the problem then how could I achieve the very similar behavior as unique_ptr with 0 cost?
Why the size of my UniqPtr objects are double in size as std::unique_ptr (even being initialized with the same values)?
Is that because of my class is storing a Del_ object as a member?
Yes.
Because D del_ needs to have storage, and every T* ptr_ has to be properly aligned
If that is the problem then how could I achieve the very similar behavior as unique_ptr with 0 cost?
You can privately derive from D, rather than have it be a member. Then an instantiation with an empty class may cave it occupy no extra storage.
template <typename T, typename D = DefDel<T>>
class UniqPtr final : D
{
public:
UniqPtr(T* = nullptr, D = {});
UniqPtr(UniqPtr const&) = delete;
UniqPtr(UniqPtr&&) noexcept;
UniqPtr& operator =(UniqPtr const&) = delete;
UniqPtr& operator =(UniqPtr&&) noexcept;
~UniqPtr();
T& operator*();
T const& operator*() const;
T* operator->();
T const* operator->() const;
operator bool() const;
private:
T* ptr_{nullptr};
};
template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(T* p, D del) :
D(del),
ptr_(p)
{}
template <typename T, typename D>
UniqPtr<T, D>::UniqPtr(UniqPtr&& rhs) noexcept :
D(std::move(*rhs)),
ptr_(std::exchange(rhs.ptr_, nullptr))
{}
template <typename T, typename D>
UniqPtr<T, D>& UniqPtr<T, D>::operator = (UniqPtr&& rhs) noexcept
{
using std::swap;
swap(static_cast<D&>(*this), static_cast<D&>(rhs));
swap(ptr_, rhs.ptr_);
}
template <typename T, typename D>
UniqPtr<T, D>::~UniqPtr()
{
static_cast<D&>(*this)(ptr_);
}

Why I get the following error: "no match for 'operator=='" ? (nested class with template)

Given the following code:
template<class T>
class TemplateClass {
T val;
public:
TemplateClass(T val) :
val(val) {
}
TemplateClass(const TemplateClass& tc) = default;
TemplateClass& operator=(const TemplateClass& tc) = default;
class Ele {
T x;
public:
Ele(T x) :
x(x) {
}
template<class S>
friend bool operator==(const typename TemplateClass<S>::Ele& e1,
const typename TemplateClass<S>::Ele& e2);
};
};
template<class T>
bool operator==(const typename TemplateClass<T>::Ele& e1,
const typename TemplateClass<T>::Ele& e2) {
return e1.x == e2.x;
}
int main() {
TemplateClass<int>::Ele e1(4);
TemplateClass<int>::Ele e2(3);
if (e1 == e2) { // *********** error
std::cout << "ok" << std::endl;
}
}
I get the following error:
no match for 'operator==' (operand types are 'TemplateClass<int>::Ele' and 'TemplateClass<int>::Ele')
Can someone tell me how can I fix it and what is the problem?
Nested name of a type belongs to non-deduced contexts:
1) The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a qualified-id:
So operator== fails to be invoked because template argument deduction fails; template parameter can't be deduced.
You might make it a non-template function, and define it inside the class definition. e.g.
template<class T>
class TemplateClass {
...
class Ele {
...
friend bool operator==(const typename TemplateClass<T>::Ele& e1,
const typename TemplateClass<T>::Ele& e2) {
return e1.x == e2.x;
}
};
};
LIVE
Or make it non-template member function, then you might define them out of the class definition. e.g.
template<class T>
class TemplateClass {
...
class Ele {
...
bool operator==(const typename TemplateClass<T>::Ele& e2) const;
bool operator!=(const typename TemplateClass<T>::Ele& e2) const;
};
};
template<class T>
bool TemplateClass<T>::Ele::operator==(const typename TemplateClass<T>::Ele& e2) const {
return x == e2.x;
}
template<class T>
bool TemplateClass<T>::Ele::operator!=(const typename TemplateClass<T>::Ele& e2) const {
return ! (*this == e2);
}
LIVE
In addition to the answers here, you can use friend injection technique to fix the error:
template<class T>
class TemplateClass {
// ...
class Ele {
// ...
friend bool operator==(const Ele& e1, const Ele& e2) {
return e1.x == e2.x;
}
};
};
Note that you do not need problematic typename TemplateClass<S>::Ele here at all.

how to avoid many similar overloads for C strings

Here is the code:
template <typename L, typename R> bool eq (const L& lhs, const R& rhs) { return lhs == rhs; }
template<int N> bool eq(char* lhs, const char(&rhs)[N]) { return String(lhs).compare(rhs) == 0; }
template<int N> bool eq(const char(&lhs)[N], char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(char* lhs, char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(const char* lhs, const char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(char* lhs, const char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(const char* lhs, char* rhs) { return String(lhs).compare(rhs) == 0; }
I have to do this for neq/lt/gt/lte/gte and not just for equality. Maybe I've already missed something.
Is there a way to not list all the possible combinations of C string types?
Also C++98.
EDIT: >> here << is an online demo with the problem
Decay an array type to pointer:
template<class T>
struct decay_array { typedef T type; };
template<class T, size_t N>
struct decay_array<T[N]> { typedef T* type; };
template<class T>
struct decay_array<T[]> { typedef T* type; };
Check that a type is not a pointer to (possibly const) char:
template<class T>
struct not_char_pointer { enum { value = true }; };
template<>
struct not_char_pointer<char*> { enum { value = false }; };
template<>
struct not_char_pointer<const char*> { enum { value = false }; };
Now check that a type is not a pointer to or array of (possibly const) char:
template<class T>
struct can_use_op : not_char_pointer<typename decay_array<T>::type> {};
Reimplement std::enable_if:
template<bool, class = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
and use it to constrain your template:
template <typename L, typename R>
typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
eq (const L& lhs, const R& rhs) { return lhs == rhs; }
Then just one overload is enough:
inline bool eq(const char* lhs, const char* rhs) { return String(lhs).compare(rhs) == 0; }
namespace details{
template<template<class...>class Z,class,class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z,class...Ts>
struct can_apply<Z,std::void_t<Z<Ts...>>,Ts...>:std::true_type{};
}
template<template<class...>class Z,class...Ts>
using can_apply=details::can_apply<Z,void,Ts...>;
This tests if a template can be applied some types.
namespace strcmp{
bool eq(const char*lhs, const char*rhs){/* body */}
}
template<class L, class R>
using str_eq_r=decltype(strcmp::eq(std::declval<L>(),std::declval<R>()));
template<class L, class R>
using can_str_eq=can_apply<str_eq_r,L,R>;
can_str_eq is truthy iff we can call stdcmp::eq on it.
namespace details {
bool eq(const char* lhs, const char* rhs, std::true_type){
return strcmp::eq(lhs,rhs);
}
template<class L,class R>
bool eq(L const& l, R const&r,std::false_type){
return l==r;
}
}
template<class L,class R>
bool eq(L const& l, R const&r){
return details::eq(l,r,can_str_eq<L const&,R const&>{});;
}
We could also use a static_if trick to do it inline, if you like:
template<class L,class R>
bool eq(L const& l, R const&r){
return static_if<can_str_eq>( l, r )(
strcmp::eq,
[](auto&& l, auto&& r){return l==r;}
);
}
After writing a static_if:
template<class...Ts>
auto functor(Ts...ts){
return [=](auto&& f){
return f(ts...);
};
}
namespace details{
template<class Functor>
auto switcher(std::true_type, Functor functor){
return [=](auto&& t, auto&&){
return functor(t);
};
}
template<class Functor>
auto switcher(std::false_type, Functor functor){
return [=](auto&&, auto&& f){
return functor(f);
};
}
}
template<template<class...>class test, class...Ts>
auto static_if(Ts...ts){
return details::switcher(
test<Ts...>{},
functor(ts...)
);
}
now, what are the odds that works? (Written on phone, not compiled yet) Also not optimal: lots of perfect forwarding, some of which requires de-lamdaing, required.

Impossibly fast Delegate in C++11 on MSVC++14

The Problem
This question relates to several questions about function pointers here (I will not list them), but most importantly it concerns the code posted here. The post claims the code should be standard compliant and it compiles on Apple Clang just fine.
I have not managed to compile it in VS2015, i.e. MSVC++14.
What could be the source of this error and why not with Clang?
First Error
First error repeats multiple times:
...\Delegate.hpp(329): error C2514: 'Delegate<R(A...)>::is_member_pair<<unnamed-symbol>>':
class has no constructors
And the same for is_member_pair_const. It relates to the following part of the code:
template <typename T>
static typename ::std::enable_if<
!(is_member_pair<T>{} ||
is_const_member_pair<T>{}),
R>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
}
Second Error
Multiple errors appear, but the first is usually most important:
...\Delegate.hpp(340): error C2059: syntax error: '<end Parse>'
...\Delegate.hpp(349): note: see reference to class template instantiation 'Delegate<R(A...)>' being compiled
Then follow a few syntax errors, unrecognizable template declaration/definition etc. The code in question:
template <typename T>
static typename ::std::enable_if<
is_member_pair<T>{} ||
is_const_member_pair<T>{},
R
>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (static_cast<T*>(object_ptr)->first->*
static_cast<T*>(object_ptr)->second)(::std::forward<A>(args)...);
}
For Completeness: The entire Delegate.hpp:
Code Source and Base Article
#pragma once
#ifndef DELEGATE_HPP
#define DELEGATE_HPP
#include <cassert>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
template <typename T> class Delegate;
template<class R, class ...A>
class Delegate<R (A...)>
{
using stub_ptr_type = R (*)(void*, A&&...);
Delegate(void* const o, stub_ptr_type const m) noexcept :
object_ptr_(o),
stub_ptr_(m)
{
}
public:
Delegate() = default;
Delegate(Delegate const&) = default;
Delegate(Delegate&&) = default;
Delegate(::std::nullptr_t const) noexcept : Delegate() { }
template <class C, typename =
typename ::std::enable_if< ::std::is_class<C>{}>::type>
explicit Delegate(C const* const o) noexcept :
object_ptr_(const_cast<C*>(o))
{
}
template <class C, typename =
typename ::std::enable_if< ::std::is_class<C>{}>::type>
explicit Delegate(C const& o) noexcept :
object_ptr_(const_cast<C*>(&o))
{
}
template <class C>
Delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
{
*this = from(object_ptr, method_ptr);
}
template <class C>
Delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
{
*this = from(object_ptr, method_ptr);
}
template <class C>
Delegate(C& object, R (C::* const method_ptr)(A...))
{
*this = from(object, method_ptr);
}
template <class C>
Delegate(C const& object, R (C::* const method_ptr)(A...) const)
{
*this = from(object, method_ptr);
}
template <
typename T,
typename = typename ::std::enable_if<
!::std::is_same<Delegate, typename ::std::decay<T>::type>{}
>::type
>
Delegate(T&& f) :
store_(operator new(sizeof(typename ::std::decay<T>::type)),
functor_deleter<typename ::std::decay<T>::type>),
store_size_(sizeof(typename ::std::decay<T>::type))
{
using functor_type = typename ::std::decay<T>::type;
new (store_.get()) functor_type(::std::forward<T>(f));
object_ptr_ = store_.get();
stub_ptr_ = functor_stub<functor_type>;
deleter_ = deleter_stub<functor_type>;
}
Delegate& operator=(Delegate const&) = default;
Delegate& operator=(Delegate&&) = default;
template <class C>
Delegate& operator=(R (C::* const rhs)(A...))
{
return *this = from(static_cast<C*>(object_ptr_), rhs);
}
template <class C>
Delegate& operator=(R (C::* const rhs)(A...) const)
{
return *this = from(static_cast<C const*>(object_ptr_), rhs);
}
template <
typename T,
typename = typename ::std::enable_if<
!::std::is_same<Delegate, typename ::std::decay<T>::type>{}
>::type
>
Delegate& operator=(T&& f)
{
using functor_type = typename ::std::decay<T>::type;
if ((sizeof(functor_type) > store_size_) || !store_.unique())
{
store_.reset(operator new(sizeof(functor_type)),
functor_deleter<functor_type>);
store_size_ = sizeof(functor_type);
}
else
{
deleter_(store_.get());
}
new (store_.get()) functor_type(::std::forward<T>(f));
object_ptr_ = store_.get();
stub_ptr_ = functor_stub<functor_type>;
deleter_ = deleter_stub<functor_type>;
return *this;
}
template <R (* const function_ptr)(A...)>
static Delegate from() noexcept
{
return { nullptr, function_stub<function_ptr> };
}
template <class C, R (C::* const method_ptr)(A...)>
static Delegate from(C* const object_ptr) noexcept
{
return { object_ptr, method_stub<C, method_ptr> };
}
template <class C, R (C::* const method_ptr)(A...) const>
static Delegate from(C const* const object_ptr) noexcept
{
return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
}
template <class C, R (C::* const method_ptr)(A...)>
static Delegate from(C& object) noexcept
{
return { &object, method_stub<C, method_ptr> };
}
template <class C, R (C::* const method_ptr)(A...) const>
static Delegate from(C const& object) noexcept
{
return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
}
template <typename T>
static Delegate from(T&& f)
{
return ::std::forward<T>(f);
}
static Delegate from(R (* const function_ptr)(A...))
{
return function_ptr;
}
template <class C>
using member_pair =
::std::pair<C* const, R (C::* const)(A...)>;
template <class C>
using const_member_pair =
::std::pair<C const* const, R (C::* const)(A...) const>;
template <class C>
static Delegate from(C* const object_ptr,
R (C::* const method_ptr)(A...))
{
return member_pair<C>(object_ptr, method_ptr);
}
template <class C>
static Delegate from(C const* const object_ptr,
R (C::* const method_ptr)(A...) const)
{
return const_member_pair<C>(object_ptr, method_ptr);
}
template <class C>
static Delegate from(C& object, R (C::* const method_ptr)(A...))
{
return member_pair<C>(&object, method_ptr);
}
template <class C>
static Delegate from(C const& object,
R (C::* const method_ptr)(A...) const)
{
return const_member_pair<C>(&object, method_ptr);
}
void reset() { stub_ptr_ = nullptr; store_.reset(); }
void reset_stub() noexcept { stub_ptr_ = nullptr; }
void swap(Delegate& other) noexcept { ::std::swap(*this, other); }
bool operator==(Delegate const& rhs) const noexcept
{
return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
}
bool operator!=(Delegate const& rhs) const noexcept
{
return !operator==(rhs);
}
bool operator<(Delegate const& rhs) const noexcept
{
return (object_ptr_ < rhs.object_ptr_) ||
((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
}
bool operator==(::std::nullptr_t const) const noexcept
{
return !stub_ptr_;
}
bool operator!=(::std::nullptr_t const) const noexcept
{
return stub_ptr_;
}
explicit operator bool() const noexcept { return stub_ptr_; }
R operator()(A... args) const
{
// assert(stub_ptr);
return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
}
private:
friend struct ::std::hash<Delegate>;
using deleter_type = void (*)(void*);
void* object_ptr_;
stub_ptr_type stub_ptr_{};
deleter_type deleter_;
::std::shared_ptr<void> store_;
::std::size_t store_size_;
template <class T>
static void functor_deleter(void* const p)
{
static_cast<T*>(p)->~T();
operator delete(p);
}
template <class T>
static void deleter_stub(void* const p)
{
static_cast<T*>(p)->~T();
}
template <R (*function_ptr)(A...)>
static R function_stub(void* const, A&&... args)
{
return function_ptr(::std::forward<A>(args)...);
}
template <class C, R (C::*method_ptr)(A...)>
static R method_stub(void* const object_ptr, A&&... args)
{
return (static_cast<C*>(object_ptr)->*method_ptr)(
::std::forward<A>(args)...);
}
template <class C, R (C::*method_ptr)(A...) const>
static R const_method_stub(void* const object_ptr, A&&... args)
{
return (static_cast<C const*>(object_ptr)->*method_ptr)(
::std::forward<A>(args)...);
}
template <typename>
struct is_member_pair : std::false_type { };
template <class C>
struct is_member_pair< ::std::pair<C* const,
R (C::* const)(A...)> > : std::true_type
{
};
template <typename>
struct is_const_member_pair : std::false_type { };
template <class C>
struct is_const_member_pair< ::std::pair<C const* const,
R (C::* const)(A...) const> > : std::true_type
{
};
template <typename T>
static typename ::std::enable_if<
!(is_member_pair<T>{} ||
is_const_member_pair<T>{}),
R
>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
}
template <typename T>
static typename ::std::enable_if<
is_member_pair<T>{} ||
is_const_member_pair<T>{},
R
>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (static_cast<T*>(object_ptr)->first->*
static_cast<T*>(object_ptr)->second)(::std::forward<A>(args)...);
}
};
namespace std
{
template <typename R, typename ...A>
struct hash<::Delegate<R (A...)> >
{
size_t operator()(::Delegate<R (A...)> const& d) const noexcept
{
auto const seed(hash<void*>()(d.object_ptr_));
return hash<typename ::Delegate<R (A...)>::stub_ptr_type>()(
d.stub_ptr_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
};
}
#endif // DELEGATE_HPP
As Igor commented, the following solves the problem: replace is_member_pair<T>{} with is_member_pair<T>::value everywhere and do the same for is_const_member_pair.

clone_ptr implementation error

I have the following implementation of a clone_ptr in an attempt to make safe copies of object pointers that need to be copied in a class, so instead of using the copy constructor, I was adviced to use smart pointers and create a clone pointer.
Clone_ptr implementation:
#include <algorithm>
#include <functional>
#include <xercesc/dom/DOM.hpp>
struct DOMImplementation_cloner
{
template <typename T>
T* operator()(T* pPtr) const
{
/* your clone code*/.
T = DOMImplementationRegistry::getDOMImplementation(X("Core"));
}
};
struct default_clone
{
template <typename T>
T* operator()(T* pPtr) const
{
return pPtr->clone();
}
};
template <typename T, typename Cloner = default_clone>
class clone_ptr
{
public:
// types
typedef T element_type;
typedef element_type value_type;
typedef const element_type const_value_type;
typedef value_type* pointer;
typedef const_value_type* const_pointer;
typedef value_type& reference;
typedef const_value_type& const_reference;
// creation
clone_ptr() :
mPtr(0)
{}
explicit clone_ptr(pointer pPtr) :
mPtr(pPtr)
{}
clone_ptr(const clone_ptr& pOther) :
mPtr(pOther.get() ? mCloner(pOther.get()) : 0)
{}
/* clone_ptr(const clone_ptr& pOther) :
mPtr(pOther.get() ? pOther->clone() : 0),
{}*/
clone_ptr& operator=(clone_ptr pOther)
{
swap(*this, pOther);
return *this;
}
~clone_ptr()
{
delete get();
}
// observers
pointer get() const
{
return mPtr;
}
pointer operator->() const
{
return get();
}
reference operator*() const
{
assert(get() != 0);
return *get();
}
// modifiers
pointer release()
{
pointer result = mPtr;
mPtr = 0;
return result;
}
void reset(pointer pPtr = 0)
{
*this = clone_ptr(pPtr);
}
// utility
friend void swap(clone_ptr& pFirst, clone_ptr& pSecond)
{
std::swap(pFirst.mPtr, pSecond.mPtr);
}
/////////////////////
// compare
template <typename T1, typename T2>
friend bool operator==(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return pFirst.get() == pSecond.get();
}
template <typename T1, typename T2>
friend bool operator!=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst == pSecond);
}
template <typename T1, typename T2>
friend bool operator<(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return std::less<void*>()(pFirst.get(), pSecond.get());
}
template <typename T1, typename T2>
friend bool operator<=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst > pSecond);
}
template <typename T1, typename T2>
friend bool operator>(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return pSecond < pFirst;
}
template <typename T1, typename T2>
friend bool operator>=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst < pSecond);
}
template <typename T1>
friend bool operator!(const clone_ptr<T1>& pX)
{
return pX.get() == 0;
}
private:
pointer mPtr;
default_clone mCloner;
};
/// Use of a xerces pointer so it can be copied/cloned safely
private class member:
clone_ptr<DOMImplementation, DOMImplementation_cloner> impl;
//compiler error:
error C2039: 'clone' : is not a member of 'xercesc_3_1::DOMImplementation'
I don't understand why it is not using the DOMImplementation_cloner and tries to use the default_clone instead?
Can someone clarify as to what I'm doing wrong?
The type of the cloner is hard-coded to default_clone, instead of using the template parameter Cloner (see the last line of your class definition).
Edit Just to make sure you understand, your definition of mCloner should look like this:
Cloner mCloner;
This way the cloner will actually be of the type given by the template parameter.
One more thing. If you expect you clone_ptr to be used in a more general setting (e.g. by coworkers on other projects), you should make the type of the cloner a property of the type T. This can be done using type traits (this answer gives an example). This could look like this in your clone_ptr:
template< typename T, typename Cloner = cloner_traits< T >::cloner_type >
class clone_ptr {
// ...
};
This would have the same default behavior as your current implementation. The advantage is that classes that require a special cloner would just specialize the cloner_traits template and the user of the class does not have to worry about choosing the appropriate cloner. If you still want to override the cloner for any class, you can still pass the cloner manually.
I recommend using clone_ptr class in following link:
http://www.codeproject.com/KB/stl/clone_ptr.aspx
The above type of clone pointer does not need to have a clone function.
There are other advantages to this type of clone pointer class, over above type implementation.
See article for more details.