I'm trying to create a function that returns the total size of a parameter pack in bytes, and am having trouble finding a solution!
template <typename... TTypes>
struct Test {
constexpr size_t getPackSizeInBytes() const {
// sizeof(TTypes) gives `unexpanded pack` error
}
};
// What I'm hoping for:
Test<uint8, uint16> test;
std::cout << test.getPackSizeInBytes() << std::endl;
// Should output 3;
Thanks for your help!
You can use a unary fold in C++17:
return (sizeof(TTypes) + ... + 0);
If you don't have C++17 then you have to unpack it in a more manual, albeit uglier way:
int sum = 0;
using I = std::size_t[];
(void)(I{0u, sum += sizeof(TTypes)...});
return sum;
Does this do what you want:
// Pre C++17 code (not sure but I belive it is easier in C++17)
#include <iostream>
#include <numeric>
template<typename... TTypes>
struct Test
{
constexpr size_t getPackSizeInBytes() const
{
size_t data[] = {sizeof(TTypes)...};
return std::accumulate(std::begin(data), std::end(data), 0);
}
};
int main()
{
Test<std::uint8_t, std::uint16_t> test;
std::cout << test.getPackSizeInBytes() << "\n";
}
Alternate (much portable, but recursive) solution, based on this answer, not even "Pre C++17", but maybe even "Pre C++11" :) (Works even in Arduino, without any dependencies)
template <typename ... Args>
struct count_bytes;
template <>
struct count_bytes<> {
constexpr static size_t value = 0u;
};
template <typename T, typename... Args>
struct count_bytes<T, Args...> {
constexpr static size_t value = sizeof(T) + count_bytes<Args...>::value;
};
// ----------------------------------------------------------------
// Compile-time testing
static_assert(count_bytes<int8_t, int16_t>::value == 3, "Test failed");
static_assert(count_bytes<int8_t, int16_t, int32_t>::value == 7, "Test failed");
static_assert(count_bytes<float, float, float, double>::value == 20, "Test failed");
// Test for known-size fixed array
static_assert(count_bytes<int, int[2]>::value == 12, "Test failed");
// Attention: sizeof(void) works for C, but not for C++. Reference: https://stackoverflow.com/a/1666232/
// static_assert(count_bytes<void>::value == 1, "Test failed");
Related
What's the easiest way to default construct an std::variant from the index of the desired type, when the index is only known at runtime? In other words, I want to write:
const auto indx = std::variant<types...>{someobject}.index();
//...somewhere later, indx having been passed around...
std::variant<types...> var = variant_from_index(indx);
///var is now set to contain a default constructed someobject
Note that indx cannot be made constexpr, so std::in_place_index doesn't work here.
The problem here is of course that since it isn't known which constructor from types... to call at compile time, somehow basically a table of all possible constructors (or maybe default constructed variants to copy from) has to be built at compile time and then accessed at run time. Some template magic is apparently in place here, but what would be the cleanest way?
I tried the following (on coliru), but the index sequence seems to come out wrong (the print in the end gives 2 0 0), and I'm confused as to why:
Edit: it works as fixed below, I had the constexpr array initialization wrong. So the question is now, is there a neater way to do this?
#include <variant>
#include <iostream>
using var_t = std::variant<int, float, const char *>;
//For debug
template<class ...types>
struct WhichType;
template<class T, class U>
struct default_variants;
template<class...Params, std::size_t... I>
struct default_variants<std::variant<Params...>, std::index_sequence<I...>> {
using variant_t = std::variant<Params...>;
//Uncomment to see the index sequence
//WhichType<std::index_sequence<I...>> idx{};
constexpr static variant_t variants[sizeof...(Params)]{variant_t{std::in_place_index<I>}...};
constexpr static std::size_t indices[sizeof...(Params)]{I...};
};
template<class T>
struct default_variants_builder;
template<class...Params>
struct default_variants_builder<std::variant<Params...>> {
using indices = std::make_index_sequence<sizeof...(Params)>;
using type = default_variants<std::variant<Params...>, indices>;
};
int main() {
using builder_t = typename default_variants_builder<var_t>::type;
var_t floatvar{1.2f};
var_t variant2 = builder_t::variants[floatvar.index()];
std::cout << "Contained " << floatvar.index() << "; Now contains " << variant2.index() << "\n";
}
With Boost.Mp11 this is basically a one-liner (as always):
template <typename V>
auto variant_from_index(size_t index) -> V
{
return mp_with_index<mp_size<V>>(index,
[](auto I){ return V(std::in_place_index<I>); });
}
Your description of the problem is accurate - you need a way to turn a runtime index into a compile-time index. mp_with_index does that for you - you give it the runtime index and the maximum compile-time index (mp_size<V> here, which would give the same value as std::variant_size_v<V> if you prefer that instead) and it will invoke a function you provide with the correct constant (I has type integral_constant<size_t, index> here, except with index being a constant expression).
How about this?
template <class Variant, std::size_t I = 0>
Variant variant_from_index(std::size_t index) {
if constexpr(I >= std::variant_size_v<Variant>)
throw std::runtime_error{"Variant index " + std::to_string(I + index) + " out of bounds"};
else
return index == 0
? Variant{std::in_place_index<I>}
: variant_from_index<Variant, I + 1>(index - 1);
}
See it live on Wandbox
Not sure if this is very elegant or not but I think it works:
#include <variant>
#include <iostream>
template<typename V, std::size_t N = std::variant_size_v<V>>
struct variant_by_index {
V make_default(std::size_t i) {
if (i >= std::variant_size_v<V>) {
throw std::invalid_argument("bad type index.");
}
constexpr size_t index = std::variant_size_v<V> - N;
if (i == index) {
return std::variant_alternative_t<index, V>();
} else {
return variant_by_index<V, N - 1>().make_default(i);
}
}
};
template<typename V>
struct variant_by_index<V, 0> {
V make_default(std::size_t i) {
throw std::bad_variant_access("bad type index.");
}
};
using var_t = std::variant<int, float, const char *>;
int main() {
variant_by_index<var_t> type_indexer;
var_t my_var_0 = type_indexer.make_default(0);
std::cout << "my_var_0 has int? " << std::holds_alternative<int>(my_var_0) << "\n";
var_t my_var_1 = type_indexer.make_default(1);
std::cout << "my_var_1 has float? " << std::holds_alternative<float>(my_var_1) << "\n";
try {
var_t my_var_1 = type_indexer.make_default(3);
} catch(const std::bad_variant_access&) {
std::cout << "Could not create with type 3.\n";
}
return 0;
}
I believe a (somewhat) elegant way might be using a more general idiom for choosing a numeric template parameter value at run time, as discussed in this question:
Idiom for simulating run-time numeric template parameters?
The foo function there will be std::get<std::size_t I> (or a lambda which captures the variant and takes no arguments).
SFINAE is quite useful to discard function bodies, but why it can't be used to discard member variables?
Is such functionality planned to be added to modern C++ at some point, ever? I tried using std::enable_if, std::conditional (which would work if it was allowed to have a type of zero size, but would probably break everything else).
I'd love to be able to generate aliases using a hypothetical SFINAE pattern like:
template<class T, SIZE>
struct Vector {
union {
T mArray[SIZE] = {};
struct {
std::declare_if<SIZE >= 1, T>::type x;
std::declare_if<SIZE >= 2, T>::type y;
std::declare_if<SIZE >= 3, T>::type z;
};
};
};
I don't see any adequate reasons for this not to exist at this point, except lack of compiler support?
If you have any idea for an elegant workaround or solution, without adding additional size to the union, or writing boilerplate code, such as a base, and then partially specialized derivations.
I'd love to know.
You can achieve pretty much what you want with the help of the c++20 attribute [[no_unique_address]],
which:
indicates that this data member need not have an address distinct from all other non-static data members of its class. This means that if the member has an empty type (e.g. stateless Allocator), the compiler may optimise it to occupy no space.
Applied to your use case:
#include <type_traits>
template <typename T, int SIZE>
struct Vector
{
T x;
[[no_unique_address]] std::conditional_t<(SIZE > 1), T, decltype([]{})> y;
[[no_unique_address]] std::conditional_t<(SIZE > 2), T, decltype([]{})> z;
};
int main()
{
static_assert(sizeof(Vector<double, 1>) == 1 * sizeof(double));
static_assert(sizeof(Vector<double, 2>) == 2 * sizeof(double));
static_assert(sizeof(Vector<double, 3>) == 3 * sizeof(double));
}
Here I've used decltype([]{}) as an empty type, yielding different types, so that they can share the same address.
It is not possible right now but you can write a templated get() function which accepts integral value. Also, if you are using C++ 17, you can use structured binding too.
#include <tuple>
#include <iostream>
// not elegant way of naming as enum will polute the whole namespace where it is defined
enum Idx {
X = 0,
Y = 1,
Z = 2,
W = 3,
R = 0,
G = 1,
B = 2,
A = 3
};
template <typename T, std::size_t SIZE>
struct Vector
{
template<std::size_t Index>
T& get() {
static_assert(Index < SIZE, "Invalid Index");
return data[Index];
}
template<std::size_t Index>
const T& get() const noexcept {
static_assert(Index < SIZE, "Invalid Index");
return data[Index];
}
T data[SIZE];
};
//only needed if structured binding is required
namespace std {
template<typename T, size_t SIZE>
struct tuple_size<Vector<T, SIZE>> {
constexpr static size_t value = SIZE;
};
template<typename T, size_t I, size_t SIZE>
struct tuple_element<I, Vector<T, SIZE>> {
using type = T;
};
}
int main()
{
Vector<int, 2> value = {0, 1};
std::cout << "x = " << value.get<X>() << ": y = " << value.get<Y>() << '\n';
// structured binding, available only in C++17
auto& [x, y] = value;
std::cout << "x = " << x << ": y = " << y << '\n';
// will generate a compiler error
//auto& [x1, y1, z1] = value;
// will invoke the static assert
//auto z = value.get<Z>();
return 0;
}
I have two functions row and col. row is a wrapper for col and should pack the return types to a tuple.
Something like this
#include <iostream>
#include <tuple>
template<typename T>
T col(size_t i)
{
return T(i);
}
template<typename ...Ts>
auto row()
{
size_t i = 0;
return std::make_tuple(col<Ts>(i++)...); //<-- undefined behaviour
}
int main()
{
auto m_row = row<int,int,double>(); //should expand to std::make_tuple(col<int>(0),col<int>(1),col<double(2));
std::cout << "std::get<0>(m_row)-" << std::get<0>(m_row) << std::endl;
std::cout << "std::get<1>(m_row)-" << std::get<1>(m_row) << std::endl;
std::cout << "std::get<2>(m_row)-" << std::get<2>(m_row) << std::endl;
return 0;
}
My problem is the integer i which has to be incremented inside the expansion from 0 up to sizeof...(Ts). I have considered index of the current type but this is not working if the types are not unique. I lack of other ideas, any help would be appreciated.
Using std::index_sequence_for we can achieve a moderately simple (but not as simple as I had hoped) solution.
As #NathanOliver mentioned, it requires a level of indirection because we need to inform a helper function of the index sequence. The top level function now looks like this:
template <typename... Ts>
auto row() {
return make_row(std::tuple<Ts...>{},
std::index_sequence_for<Ts...>{});
}
So the helper function takes a default constructed tuple of the type requested, and the compile time sequence of integers.
All the helper needs to do now is to construct a Tuple using the index sequence (0, 1, ...).
template <typename Tuple, std::size_t... Is>
auto make_row(Tuple, std::index_sequence<Is...>) {
return Tuple{ Is... };
}
Finally, to verify this does what we wanted:
int main()
{
auto r = row<int,int,double>();
static_assert(std::is_same<decltype(r), std::tuple<int, int, double>>::value);
}
Suppose I have 3 bool type values
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
I would like to set a bitset denoting the three
std::bitset<3> foo;
How can I construct a bitset using the boolean values?
I want to do something like this
std::bitset<3> foo(canWalk,cantalk,caneat); //giving me 100
Following the example of Shivendra Agarwal, but using the constructor that receive an unsigned long long, I propose the following variadic template function (to be more generic)
template <typename ... Args>
unsigned long long getULL (Args ... as)
{
using unused = int[];
unsigned long long ret { 0ULL };
(void) unused { 0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)... };
return ret;
}
that permit the initialization of foo as follows
std::bitset<3> foo{ getULL(canwalk, cantalk, caneat) };
This works only if the dimension of the std::bitset isn't grater of the number of bits in an unsigned long long (with 3 whe are surely safe).
The following is a full working example
#include <bitset>
#include <iostream>
template <typename ... Args>
unsigned long long getULL (Args ... as)
{
using unused = int[];
unsigned long long ret { 0ULL };
(void) unused { 0, (ret <<= 1, ret |= (as ? 1ULL : 0ULL), 0)... };
return ret;
}
int main()
{
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
std::bitset<3> foo{ getULL(canwalk, cantalk, caneat) };
std::cout << foo << std::endl;
}
IMHO, an initialization of type
std::bitset<3> foo(canWalk, cantalk, caneat);
is dangerous (error prone) because require that the template argument of std::bitset (3, in the example) correspond to the number of argument of the initialization.
I propose the creation of a "make" function (following the consolidated example of std::pair(), std::tuple(), std::make_unique(), std::make_shared) where the type and the number of arguments fix the returned type.
So I propose the following makeBitSet() function that return a std::bitset<N> where N is the number of the arguments
template <typename ... Args>
std::bitset<sizeof...(Args)> makeBitSet (Args ... as)
{
using unused = bool[];
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
(void) unused { true, (ret.set(--ui, as), true)... };
return ret;
}
The function can be used as follows
std::bitset<3> foo{ makeBitSet(canwalk, cantalk, caneat) };
but also (better, IMHO), using the C++11 auto,
auto foo = makeBitSet(canwalk, cantalk, caneat);
Observe that, starting from C++14, makeBitSet() can use the returning auto type
template <typename ... Args>
auto makeBitSet (Args ... as)
{
// ...
avoiding the annoying std::bitset<sizeof...(Args)> redundancy.
Moreover, starting from C++17, you can use template folding and, throwing away the unused array (and the corresponding using declaration), the makeBitSet() can be simplified as [EDIT: modified, to improve performances, following a suggestion from Mooing Duck (thanks!)]
template <typename ... Args>
auto makeBitSet (Args ... as)
{
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
( ret.set(--ui, as), ... );
return ret;
}
The following is a full working C++11 example
#include <bitset>
#include <iostream>
template <typename ... Args>
std::bitset<sizeof...(Args)> makeBitSet (Args ... as)
{
using unused = bool[];
std::bitset<sizeof...(Args)> ret;
std::size_t ui { ret.size() };
(void) unused { true, (ret.set(--ui, as), true)... };
return ret;
}
int main()
{
bool canwalk { true };
bool cantalk { false };
bool caneat { false };
auto foo = makeBitSet(canwalk, cantalk, caneat);
std::cout << foo << std::endl;
}
Introduce a new api that can give you string input that bitset accepts in parameter.
to be more generic, recommendation will be to use bool array or [std::vector<bool>][1] to get rid of these variable parameters in getString()
inline std::string getString(bool canwalk, bool canTalk, bool canEat)
{
std::stringstream input;
str << canwalk?1:0 << cantalk?1:0 << caneat?1:0;
return input.str();
}
now can define bitset as:
std::bitset<3> foo (getString(canwalk, canTalk, canEat));
You basically need a builder that will build an initial value from your boolean set to pass to the constructor of std::bitset. You can do this at compile time (as opposed to runtime) via variadic templates, like so:
template <unsigned long long initialValue>
constexpr unsigned long long bitset_value_builder_impl() { return initialValue; }
template <unsigned long long initialValue, typename First, typename ... Args>
constexpr unsigned long long bitset_value_builder_impl(First &&first, Args &&...args) {
return first ?
bitset_value_builder_impl< (initialValue | (1UL<<sizeof...(args)) ), Args...>(std::forward<Args>(args)...) :
bitset_value_builder_impl< (initialValue & ~(1UL<<sizeof...(args)) ), Args...>(std::forward<Args>(args)...);
}
template <typename First, typename ... Args>
constexpr unsigned long long bitset_value_builder(First &&first, Args &&...args) {
return bitset_value_builder_impl<0, First, Args...>(std::forward<First>(first), std::forward<Args>(args)...);
}
int main()
{
bool canwalk=true;
bool cantalk=false;
bool caneat=false;
std::bitset<3> bits{bitset_value_builder(canwalk, cantalk, caneat)};
std::cout << bits << std::endl; //100
}
I am experimenting with some tuples, and I find myself in the weird position of asking this: how can I copy two tuples that differ in their sizes? Of course, this is intended limited to the minimum length of the two tuples.
So, for instance, let's create three tuples:
std::tuple<int, char, float> a(-1, 'A', 3.14);
std::tuple<int, char, double> b = a;
std::tuple<long, int, double, char> c;
Now, a and b differ in types, and the assignment work (obviously). As for a and c the things get a little more confusing.
My first implementation failed, since I don't know how to recurse on variadic templates with a specific type, so something like this won't work:
template <class T, class U>
void cp(std::tuple<T> from, std::tuple<U> to)
{
}
template <class T, class... ArgsFrom, class U, class... ArgsTo>
void cp(std::tuple<T, ArgsFrom...> from, std::tuple<U, ArgsTo...> to)
{
std::get<0>(to) = std::get<0>(from);
// And how to generate the rest of the tuples?
}
That function won't do anything. So I've devised a second failing attempt, using not the types, but the sizes:
template<class From, class To, std::size_t i>
void copy_tuple_implementation(From &from, To &to)
{
std::get<i>(to) = std::get<i>(from);
copy_tuple_implementation<From, To, i - 1>(from, to);
}
template<>
void copy_tuple_implementation<class From, class To, 0>(From &from, To &to)
{
}
template<class From, class To>
void copy_tuple(From &from, To &to)
{
constexpr std::size_t from_len = std::tuple_size<From>::value;
constexpr std::size_t to_len = std::tuple_size<To>::value;
copy_tuple_implementation<From, To, from_len < to_len ? from_len - 1 : to_len - 1>(from, to);
}
But that won't compile. I have too many errors to display here, but the most significant ones are:
Static_assert failed "tuple_element index out of range"
No type named 'type' in 'std::__1::tuple_element<18446744073709551612, std::__1::__tuple_types<> >'
Read-only variable is not assignable
No viable conversion from 'const base' (aka 'const __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, int, int, double>') to 'const __tuple_leaf<18446744073709551615UL, type>'
The interesting part is the index out of range, and the fact that I cannot copy an element with std::get<>.
Can anyone help me in this?
Thanks!
Here's one possibility, using C++14's ready-made integer sequence template (but this is easily reproduced manually if your library doesn't include it):
#include <tuple>
#include <utility>
template <std::size_t ...I, typename T1, typename T2>
void copy_tuple_impl(T1 const & from, T2 & to, std::index_sequence<I...>)
{
int dummy[] = { (std::get<I>(to) = std::get<I>(from), 0)... };
static_cast<void>(dummy);
}
template <typename T1, typename T2>
void copy_tuple(T1 const & from, T2 & to)
{
copy_tuple_impl(
from, to,
std::make_index_sequence<std::tuple_size<T1>::value>());
}
Example:
#include <iostream>
int main()
{
std::tuple<int, char> from { 1, 'x' };
std::tuple<int, char, bool> to;
copy_tuple(from, to);
std::cout << "to<0> = " << std::get<0>(to) << "\n";
}
Another option is to use operator overloading to simulate partial-specialization of your function:
template <std::size_t N>
struct size_t_t {};
template<class From, class To, std::size_t i>
void copy_tuple_implementation(From &from, To &to, size_t_t<i>)
{
std::get<i>(to) = std::get<i>(from);
copy_tuple_implementation(from, to, size_t_t<i-1>{});
}
template<class From, class To>
void copy_tuple_implementation(From &from, To &to, size_t_t<0>)
{
std::get<0>(to) = std::get<0>(from);
}
Or you could just use a helper class:
template<class From, class To, std::size_t i>
struct CopyTuple
{
static void run(From &from, To &to)
{
std::get<i>(to) = std::get<i>(from);
CopyTuple<From,To,i-1>::run(from, to);
}
};
template<class From, class To>
struct CopyTuple<From,To,0>
{
static void run(From &from, To &to)
{
std::get<0>(to) = std::get<0>(from);
}
};
The goal here is to get a clean syntax at point of use.
I define auto_slice which takes a tuple, and auto slices it for the expression.
The intended use is
auto_slice(lhs)=auto_slice(rhs);
and it just works.
// a helper that is a slightly more conservative `std::decay_t`:
template<class T>
using cleanup_t = std::remove_cv_t< std::remove_reference_t< T > >;
// the workhorse. It holds a tuple and in an rvalue context
// allows partial assignment from and to:
template<class T,size_t s0=std::tuple_size<cleanup_t<T>>{}>
struct tuple_slicer{
T&&t;
// Instead of working directly within operators, the operators
// call .get() and .assign() to do their work:
template<class Dest,size_t s1=std::tuple_size<Dest>{}>
Dest get() && {
// get a pack of indexes, and use it:
using indexes=std::make_index_sequence<(s0<s1)?s0:s1>;
return std::move(*this).template get<Dest>(indexes{});
}
template<class Dest,size_t s1=std::tuple_size<Dest>{},size_t...is>
Dest get(std::index_sequence<is...>) && {
// We cannot construct a larger tuple from a smaller one
// as we do not know what to populate the remainder with.
// We could default construct them, I guess?
static_assert(s0>=s1,"use auto_slice on target");
using std::get;
return Dest{ get<is>(std::forward<T>(t))... };
}
// allows implicit conversion from the slicer:
template<class Dest>
operator Dest()&&{
return std::move(*this).template get<Dest>();
}
// now we are doing the assignment work. This function
// does the pack expansion hack, excuse the strangeness of the
// code in it:
template<class Src, size_t...is>
void assign(std::index_sequence<is...>,tuple_slicer<Src>&&rhs)&&{
using std::get;
int _[]={0,(void(
get<is>(std::forward<T>(t))=get<is>(std::forward<Src>(rhs.t))
),0)...};
(void)_; // remove warnings
}
// assign from another slicer:
template<class Src,size_t s1>
void operator=(tuple_slicer<Src,s1>&&rhs)&&{
using indexes=std::make_index_sequence<(s0<s1)?s0:s1>;
std::move(*this).assign(indexes{},std::move(rhs));
}
// assign from a tuple. Here we pack it up in a slicer, and use the above:
template<class Src>
void operator=(Src&& src)&&{
std::move(*this) = tuple_slicer<Src>{ std::forward<Src>(src) };
}
};
// this deduces the type of tuple_slicer<?> we need for us:
template<class Tuple>
tuple_slicer<Tuple> auto_slice(Tuple&&t){
return {std::forward<Tuple>(t)};
}
The slice is only required on whichever side is smaller, but can be done on both sides (for generic code) if required.
It also works at construction. On the right hand side, it should work with std::arrays and pairs and tuples. On the left hand side, it may not work with arrays, due to requirement to construct with {{}}.
live example
Here is the recursive solution your were originally trying to figure out:
#include <tuple>
// Limit case
template<std::size_t I = 0, typename ...From, typename ...To>
typename std::enable_if<(I >= sizeof...(From) || I >= sizeof...(To))>::type
copy_tuple(std::tuple<From...> const & from, std::tuple<To...> & to) {}
// Recursive case
template<std::size_t I = 0, typename ...From, typename ...To>
typename std::enable_if<(I < sizeof...(From) && I < sizeof...(To))>::type
copy_tuple(std::tuple<From...> const & from, std::tuple<To...> & to)
{
std::get<I>(to) = std::get<I>(from);
copy_tuple<I + 1>(from,to);
}
You do not need std::index_sequence or similar apparatus, and this
solution has two strengths that your accepted one does not:
It will compile, and do the right thing, when from is longer than to: the
excess trailing elements of from are ignored.
It will compile, and do the right thing, when either from or to is an
empty tuple: the operation is a no-op.
Prepend it to this example:
#include <iostream>
int main()
{
std::tuple<int, char> a { 1, 'x' };
std::tuple<int, char, bool> b;
// Copy shorter to longer
copy_tuple(a, b);
std::cout << "b<0> = " << std::get<0>(b) << "\n";
std::cout << "b<1> = " << std::get<1>(b) << "\n";
std::cout << "b<2> = " << std::get<2>(b) << "\n\n";
// Copy longer to shorter
std::get<0>(b) = 2;
std::get<1>(b) = 'y';
copy_tuple(b,a);
std::cout << "a<0> = " << std::get<0>(a) << "\n";
std::cout << "a<1> = " << std::get<1>(a) << "\n\n";
// Copy empty to non-empty
std::tuple<> empty;
copy_tuple(empty,a);
std::cout << "a<0> = " << std::get<0>(a) << "\n";
std::cout << "a<1> = " << std::get<1>(a) << "\n\n";
// Copy non-empty to empty
copy_tuple(a,empty);
return 0;
}
(g++ 4.9/clang 3.5, -std=c++11)