Skip to content

Instantly share code, notes, and snippets.

@gintenlabo
Created July 16, 2013 09:29
Show Gist options
  • Select an option

  • Save gintenlabo/6007230 to your computer and use it in GitHub Desktop.

Select an option

Save gintenlabo/6007230 to your computer and use it in GitHub Desktop.
Etude explicit-copy framework (draft)
#include <type_traits>
#include <utility>
namespace etude {
namespace copy_impl_ {
struct base_ {};
struct derived_ : base_ {};
template<class T>
struct is_copy_constructible
: std::is_convertible<T const&, T>::type {
};
template<class T>
struct is_move_constructible
: std::is_convertible<T&&, T>::type {
};
template<class T>
void etude_copy_explicitly(T const&) = delete;
template<class T>
void copy_(T const& x, ...) {
static_assert(!std::is_same<T, T>::value, "should not be odr-used");
}
template<class T,
typename std::enable_if<
is_copy_constructible<T>::value, int>::type = 0
>
T copy_(T const& x, void*) {
return x;
}
template<class T,
typename std::enable_if<
std::is_convertible<
decltype(std::declval<T const&>().copy()), T>::value,
int>::type = 0
>
T copy_(T const& x, base_*) {
return x.copy();
}
template<class T,
typename std::enable_if<
std::is_convertible<
decltype(etude_copy_explicitly(std::declval<T const&>())),
T>::value,
int>::type = 0
>
T copy_(T const& x, derived_*) {
return etude_copy_explicitly(x);
}
template<class T>
auto invoke_copy_(T const& x)
-> decltype(copy_impl_::copy_(x, (derived_*)0)) {
return copy_impl_::copy_(x, (derived_*)0);
}
template<class T>
struct is_explicitly_copyable
: std::is_same<T, decltype(
copy_impl_::invoke_copy_(std::declval<T const&>()))>::type {
};
template<class T,
typename std::enable_if<
std::is_same<typename std::decay<T>::type, T>::value, int>::type = 0,
typename std::enable_if<
is_explicitly_copyable<T>::value, int>::type = 0
>
T copy(T const& x) {
return copy_impl_::invoke_copy_(x);
}
template<class T,
typename std::enable_if<
std::is_same<typename std::decay<T>::type, T>::value, int>::type = 0,
typename std::enable_if<
is_move_constructible<T>::value, int>::type = 0
>
T copy(T&& x) {
return std::forward<T>(x);
}
} // namespace copy_impl_
namespace copy_ {
using copy_impl_::is_explicitly_copyable;
using copy_impl_::is_copy_constructible;
using copy_impl_::is_move_constructible;
using copy_impl_::copy;
}
using namespace copy_;
} // namespace etude
struct noncopyable {
noncopyable() = default;
noncopyable(noncopyable&&) = default;
noncopyable& operator=(noncopyable&&) = default;
};
struct Hoge : private noncopyable {
Hoge copy() const {
return Hoge{};
}
};
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
int main() {
STATIC_ASSERT( etude::is_explicitly_copyable<int>::value);
// rvalue
etude::copy(1);
// lvalue
{
int i = 1;
int j = etude::copy(i);
(void)j;
}
STATIC_ASSERT(!etude::is_explicitly_copyable<noncopyable>::value);
STATIC_ASSERT(!etude::is_copy_constructible<noncopyable>::value);
STATIC_ASSERT( etude::is_move_constructible<noncopyable>::value);
// rvalue
etude::copy(noncopyable{});
STATIC_ASSERT( etude::is_explicitly_copyable<Hoge>::value);
STATIC_ASSERT(!etude::is_copy_constructible<Hoge>::value);
STATIC_ASSERT( etude::is_move_constructible<Hoge>::value);
// rvalue
etude::copy(Hoge{});
// lvalue
{
Hoge x;
auto y = etude::copy(x);
(void)y;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment