Created
June 14, 2017 00:34
-
-
Save mpark/c739254df16e341d520bfff8cd280958 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <tuple> | |
#include <experimental/tuple> | |
#include <type_traits> | |
#include <utility> | |
// The same limitations apply to std::less if we wanted to figure out the winner | |
// of an overload resolution of `<`. | |
// it's a more general problem than for constructors. | |
template <typename T> | |
struct direct_init { | |
template <typename... Args> | |
auto operator()(Args &&... args) const | |
-> decltype(T(std::forward<Args>(args)...)) { | |
return T(std::forward<Args>(args)...); | |
} | |
}; | |
template <typename T> | |
struct direct_list_init { | |
template <typename... Args> | |
auto operator()(Args &&... args) const | |
-> decltype(T{std::forward<Args>(args)...}) { | |
return T{std::forward<Args>(args)...}; | |
} | |
}; | |
template <typename T> | |
struct copy_init { | |
template <typename Arg> | |
std::enable_if_t<std::is_convertible<T, Arg &&>>, | |
T> operator()(Arg &&arg) const { | |
return std::forward<Arg>(arg); | |
} | |
}; | |
template <typename T, typename... Args> | |
struct is_copy_list_initializable { | |
private: | |
static std::true_type impl(T, std::nullptr_t); | |
template <typename U> | |
static std::false_type impl(U, void *); | |
public: | |
static constexpr bool value = | |
decltype(impl({std::declval<Args>()...}, nullptr))::value; | |
}; | |
template <typename T, typename... Args> | |
static constexpr bool is_copy_list_initializable_v = | |
is_copy_list_initializable<T, Args...>::value; | |
template <typename T> | |
struct copy_list_init { | |
template <typename... Args> | |
std::enable_if_t<is_copy_list_initializable_v<T, Args &&...>, | |
T> operator()(Args &&... args) const { | |
return {std::forward<Args>(args)...}; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Obj { | |
Obj(long) { std::cout << "A" << std::endl; } | |
Obj(std::initializer_list<int>) { std::cout << "B" << std::endl; } | |
explicit Obj(int) { std::cout << "C" << std::endl; } | |
}; | |
// The problem we can solve with this: | |
// Improving tuple & pair.. yet again... maybe... for the... last-ish time? | |
/* | |
template <typename T, typename U> | |
struct pair { | |
// BEFORE | |
// If `(is_convertible<X&&, T> && is_contructible<T, X&&>) && | |
// (is_convertible<Y&&, U> && is_contructible<U, Y&&>)`. | |
template <typename X, typename Y> | |
pair(X &&x, Y &&y) : t(std::forward<X>(x)), u(std::forward<Y>(y)) {} | |
// AFTER | |
// If `is_convertible<X&&, T> && is_convertible<Y&&, U>`. | |
template <typename X, typename Y> | |
pair(X &&x, Y &&y) | |
: t(copy_init<T>{}(std::forward<X>(x))), | |
u(copy_init<U>{}(std::forward<Y>(y))) {} | |
// If we were to try to do this in language... | |
// If `is_convertible<X&&, T> && is_convertible<Y&&, U>`. | |
template <typename X, typename Y> | |
pair(X &&x, Y &&y) : t = std::forward<X>(x), u = std::forward<Y>(y) {} | |
// If `is_contructible<T, X&&> && is_constructible<T, Y&&>` | |
template <typename X, typename Y> | |
explicit pair(X &&x, Y &&y) : t(std::forward<X>(x)), u(std::forward<Y>(y)) {} | |
T t; | |
U u; | |
}; | |
*/ | |
int main() { | |
Obj x0(0); // direct-init | |
Obj x1{0}; // direct-list-init | |
Obj x2 = 0; // copy-init | |
Obj x3 = {0}; // copy-list-init | |
(void)x0; | |
(void)x1; | |
(void)x2; | |
(void)x3; | |
std::cout << std::endl; | |
direct_init<Obj>{}(0); | |
direct_list_init<Obj>{}(0); | |
copy_init<Obj>{}(0); | |
copy_list_init<Obj>{}(0); | |
std::cout << std::endl; | |
// std::make_from_tuple | |
std::experimental::apply(direct_init<Obj>{}, std::forward_as_tuple(0)); | |
// others | |
std::experimental::apply(direct_list_init<Obj>{}, std::forward_as_tuple(0)); | |
std::experimental::apply(copy_init<Obj>{}, std::forward_as_tuple(0)); | |
std::experimental::apply(copy_list_init<Obj>{}, std::forward_as_tuple(0)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment