How to remove the nth element from a tuple? - algorithm

I'm trying to write a function that creates a new std::tuple from an existing one, with skipping the element on a given index. In example:
I have a tuple t defined as below:
constexpr auto t = std::tuple(1, 2, 3, 4);
And I want to copy it to another tuple. However, I want to skip the nth element. Let's say that in this case, the nth element I want to skip is 3 (this would mean that I want to skip the element with the index 2). This would result in a new tuple defined as:
std::tuple(1, 2, 4);
This is the closest I got until now:
template<std::size_t N, typename T, std::size_t ... is>
constexpr auto fun(T&& tp, std::index_sequence<is...>&& i) noexcept {
return std::tuple((is != N ? std::get<is>(tp) : 0) ...);
}
template<std::size_t N, std::size_t... elems>
constexpr auto fun2() noexcept {
constexpr auto t = std::tuple(elems...);
return fun<N>(std::forward_as_tuple(elems...), std::make_index_sequence<sizeof...(elems)>());
}
However, instead of removing the nth element, I set it to 0.
Ideally, I would change the return argument in the function fun() to create a new tuple using multiple temporary tuples:
return std::tuple_cat((is != N ? std::tuple(std::get<is>(tp)) : std::tuple()) ...);
However, the issue with this is that the ternary operator has to have matching types on both sides.
Another approach I tried was based on recursion:
template<std::size_t N, std::size_t head, std::size_t... tail>
constexpr auto fun3() noexcept {
if constexpr(!sizeof...(tail))
return std::tuple(head);
if constexpr(sizeof...(tail) - 1 == N)
return std::tuple_cat(fun3<N, tail...>());
if constexpr(sizeof...(tail) - 1 != N)
return std::tuple_cat(std::tuple(head), fun3<N, tail...>());
}
However, that was even more unsuccessful. In this case, if N is equal to 0, the nth element (which is the first element here as well) will still be used in the new tuple. Also, this won't even compile, because there's an issue with the second statement:
if constexpr(sizeof...(tail) - 1 == N)
What am I missing here? How can I copy a tuple and skip one of its elements during the copy?
I'm using C++17, and I need the function to be evaluated during compile-time.

What about
return std::tuple_cat( foo<is, N>::func(std::get<is>(tp)) ...);
where foo is a struct with specialization as follows?
template <std::size_t, std::size_t>
struct foo
{
template <typename T>
static auto func (T const & t)
{ return std::make_tuple(t); }
}
template <std::size_t N>
struct foo<N, N>
{
template <typename T>
static std::tuple<> func (T const &)
{ return {}; }
}
(caution: code not tested).
This is almost your ternary operator idea but without the problem of matching the types in both sides: only the right type is instantiated.

Another solution would be to create two index sequences that refer to the before and after parts of the tuple.
template<std::size_t nth, std::size_t... Head, std::size_t... Tail, typename... Types>
constexpr auto remove_nth_element_impl(std::index_sequence<Head...>, std::index_sequence<Tail...>, std::tuple<Types...> const& tup) {
return std::tuple{
std::get<Head>(tup)...,
// We +1 to refer one element after the one removed
std::get<Tail + nth + 1>(tup)...
};
}
template<std::size_t nth, typename... Types>
constexpr auto remove_nth_element(std::tuple<Types...> const& tup) {
return remove_nth_element_impl<nth>(
std::make_index_sequence<nth>(), // We -1 to drop one element
std::make_index_sequence<sizeof...(Types) - nth - 1>(),
tup
);
}
Here's a test for this function:
int main() {
constexpr auto tup = std::tuple{1, 1.2, 'c'};
constexpr auto tup2 = remove_nth_element<0>(tup);
constexpr auto tup3 = remove_nth_element<2>(tup);
static_assert(std::is_same_v<decltype(tup2), const std::tuple<double, char>>);
static_assert(std::is_same_v<decltype(tup3), const std::tuple<int, double>>);
return 0;
}
Live example
This solution has the advantages of not constructing intermediary tuples and not using std::tuple_cat, which both can be hard on compile times.

Just a few minutes after posting the question, I found a workaround. It's not ideal, but hey:
template<std::size_t N, typename T, std::size_t ... is>
constexpr auto fun(T&& tp, std::index_sequence<is...>&& i) noexcept {
return std::tuple((is < N ? std::get<is>(tp) : std::get<is+1>(tp)) ...);
}
template<std::size_t N, std::size_t... elems>
constexpr auto fun2() noexcept {
constexpr auto t = std::tuple(elems...);
return fun<N>(std::forward_as_tuple(elems...), std::make_index_sequence<sizeof... (elems) - 1>());
}
This way, we copy all of the elements prior to the nth element, and when we reach the nth element, we increase every next index for 1. We won't go out of range, since we pass the index_sequence that has 1 element less than the tuple that is passed.
I hope that this answer helps someone.

Related

Why does this partial specialization of a template friend function work?

I am writing simple classes that implement vectors and matrices as part of trying to learn OpenGL. I have matrix and vector classes that look like this :
// Forward declarations
template <typename T, size_t N/*len*/> struct vec;
template<typename T, size_t N /*rows*/, size_t M /*cols*/> struct mat;
// Forward declare *operator for matrix
// (NxM) matrix multiplied by (MxP) matrix yields (NxP) matrix
mat<T, N, P> operator* (const mat<T, N, M>& A, const mat<T, M, P>& B);
template <typename T, size_t N>
struct vec {
public:
vec() {}
virtual ~vec() {}
private:
T[N] m_data;
};
template <typename T, size_t N, size_t M>
struct mat {
public:
mat() {}
virtual ~mat() {}
// This is where it gets interesting. By my reading of the rules
// of C++11, this counts as a partial specialization of the
// operator template, and should not work.
// However, it compiles just fine!
template <size_t n, size_t m, size_t p>
friend mat<T, n, p> operator* (const mat<T, n, m>& A,
const mat<T, m, p> &B);
// Implementation appears later in the same header file.
private:
T[N*M] m_data;
};
I declare the * operator as a friend because I want it to have access to the internal m_data member, but I don't want the users of 'mat' and 'vec' to know the internals.
This compiles and runs just fine. I have a unit test for that matrix multiplication, and it works just fine. However, I don't know why it even compiles, let alone runs. By my reading of the rules of C++ templates, the declaration of the * operator counts as a partial specialization of function template, and is illegal.
What am I missing here?
Turns out this does *NOT* compile. I thought it was compiling because I wasn't invoking the template stream operator in my unit test when I thought I was.
Sorry for the stupid question!

Variadic Template Recursion

I am trying to use recursion to solve this problem where if i call
decimal<0,0,1>();
i should get the decimal number (4 in this case).
I am trying to use recursion with variadic templates but cannot get it to work.
Here's my code;
template<>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a*2 + decimal<pack...>();
};
int main(int argc, char *argv[]){
cout<<decimal<0,0,1>()<<endl;
return 0;
}
What would be the best way to solve this?
template<typename = void>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a + 2*decimal<pack...>();
};
The problem was with the recursive case, where it expects to be able to call decltype<>(). That is what I have defined in the first overload above. You can essentially ignore the typename=void, the is just necessary to allow the first one to compile.
A possible solution can be the use of a constexpr function (so you can use it's values it's value run-time, when appropriate) where the values are argument of the function.
Something like
#include <iostream>
constexpr int decimal ()
{ return 0; }
template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
{ return a*2 + decimal(pack...); }
int main(int argc, char *argv[])
{
constexpr int val { decimal(0, 0, 1) };
static_assert( val == 2, "!");
std::cout << val << std::endl;
return 0;
}
But I obtain 2, not 4.
Are you sure that your code should return 4?
-- EDIT --
As pointed by aschepler, my example decimal() template function return "eturns twice the sum of its arguments, which is not" what do you want.
Well, with 0, 1, true and false you obtain the same; with other number, you obtain different results.
But you can modify decimal() as follows
template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
{ return a*2 + decimal(pack...); }
to avoid this problem.
This is a C++14 solution. It is mostly C++11, except for std::integral_sequence nad std::index_sequence, both of which are relatively easy to implement in C++11.
template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;
template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;
template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};
template<std::uint64_t... xs>
struct or_bits : uint64<0> {};
template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};
template<bool...bs, std::size_t...Is>
constexpr
uint64<
or_bits<
uint64<
bs?bit<Is>:std::uint64_t(0)
>{}...
>{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
(void)bits; // suppress warning
return {};
}
template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }
It generates the resulting value as a type with a constexpr conversion to scalar. This is slightly more powerful than a constexpr function in its "compile-time-ness".
It assumes that the first bit is the most significant bit in the list.
You can use from_binary<1,0,1>() or from_binary( bools<1,0,1>{} ).
Live example.
This particular style of type-based programming results in code that does all of its work in its signature. The bodies consist of return {};.

c++ 11. Matrices multiplication

Hello. I write matrix class but i have some problem with matrices multiplication which have different dimensions.
template< typename T, size_t Row, size_t Col >
class Matrix
{
public:
.....................................
template< typename MulT >
auto operator * (const MulT& other) -> Matrix<T, Row, other.getColNum()>
{
if (other.getRowNum() != getColNum())
throw std::logic_error("Multiplication are not possible");
Matrix<T, Row, other.getColNum()> temp;
// Some operations.
return temp; // Must return matrix with this type Matrix<T, Row, other.getColNum()>
// but it dont work.
}
.....................................
}; // class Matrix
This code don't work. It is possible to resolve this problem?
other.getColNum() is probably not a constexpr function and can therefore not be used as a template non-type argument.
Read up on constexpr here: http://en.cppreference.com/w/cpp/language/constexpr
You don't want to check the if if (other.getRowNum() != getColNum()) at runtime, this should be done at compile time. One way to do this is to define the operator only for when the multiplication is valid. In this case:
template< typename T, size_t Row, size_t Col >
class Matrix
{
public:
.....................................
template<size_t _RHSWIDTH>
Matrix<_T, _RHSWIDTH, Row> operator * (const Matrix<T, _RHSWIDTH, Col> &rhs) const
{
Matrix<_T, _RHSWIDTH, Row> temp;
// Some operations.
return temp;
}
.....................................
}; // class Matrix
As a result, any attempt to multiply matrices which cannot be multiplied will fail at compile time. For a complete example, I wrote a complete matrix template a long time ago which uses very similar syntax: https://github.com/Enseed/GenericGeometry/blob/master/Matrix.h

std::tuple_element need deep template instantination

in here http://en.cppreference.com/w/cpp/utility/tuple/tuple_element given possible implementation of std::tuple_element.
template< std::size_t I, class T >
struct tuple_element;
// recursive case
template< std::size_t I, class Head, class... Tail >
struct tuple_element<I, std::tuple<Head, Tail...>>
: std::tuple_element<I-1, std::tuple<Tail...>> { };
// base case
template< class Head, class... Tail >
struct tuple_element<0, std::tuple<Head, Tail...>> {
typedef Head type;
};
But, this implementation need deep recursion instantiation, if tuple has a lot parameters ( more that 100 or 200 parameters).
Q1: Why C++11 was not added special operator for getting elements by index?
like tuple[2] or tuple[0] ?
Q2: Is possible reduce the deep instantiation? For example in D language more template algorithms (in typetuple) needed O(log(N) ) deep instantiation.
EDIT: Q1: Why C++11 was not added special operator for getting elements by index from variadic templates?
like template< class ...T> struct index{ typedef T[3] third_element;}
I think this implementation has O(log(N)) instantiation depth; kudos to Xeo for the O(log(N)) indices trick (modified to use std::size_t instead of unsigned).
Edit: I realized there's a different, simpler and probably faster (compilation time) solution to get the nth type of a tuple.
// from https://stackoverflow.com/a/13073076
// indices trick in O(log(N)) instantiations, by Xeo
// using aliases for cleaner syntax
template<class T> using Invoke = typename T::type;
template<std::size_t...> struct seq{ using type = seq; };
template<class S1, class S2> struct concat;
template<std::size_t... I1, std::size_t... I2>
struct concat<seq<I1...>, seq<I2...>>
: seq<I1..., (sizeof...(I1)+I2)...>{};
template<class S1, class S2>
using Concat = Invoke<concat<S1, S2>>;
template<std::size_t N> struct gen_seq;
template<std::size_t N> using GenSeq = Invoke<gen_seq<N>>;
template<std::size_t N>
struct gen_seq : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};
template<> struct gen_seq<0> : seq<>{};
template<> struct gen_seq<1> : seq<0>{};
Implementation of / similar to std::tuple_element:
namespace detail
{
template<std::size_t>
struct Any
{
Any(...) {}
};
template<typename T>
struct wrapper { using type = T; };
template<std::size_t... Is>
struct get_nth_helper
{
template<typename T>
static auto deduce(Any<Is>..., wrapper<T>, ...) -> wrapper<T>;
};
template<std::size_t... Is, typename... Ts>
auto deduce_seq(seq<Is...>, wrapper<Ts>... pp)
-> decltype( get_nth_helper<Is...>::deduce(pp...) );
}
#include <tuple>
template<std::size_t n, class Tuple>
struct tuple_element;
template<std::size_t n, class... Ts>
struct tuple_element<n, std::tuple<Ts...>>
{
using wrapped_type = decltype( detail::deduce_seq(gen_seq<n>{},
detail::wrapper<Ts>()...) );
using type = typename wrapped_type::type;
};
Usage example:
#include <typeinfo>
#include <iostream>
int main()
{
std::tuple<int, double, bool, char> t;
tuple_element<1, decltype(t)>::type x;
std::cout << typeid(x).name() << std::endl;
}
Thanks to #Barry for pointing out an issue in an earlier version of this answer with function/array types, and providing a fix.
Original version:
(Note: This version is simplified and doesn't add cv-qualifiers.)
#include <tuple>
namespace detail
{
template < std::size_t Index, class Arg >
struct s_get_one
{
// declare a function that links an Index with an Arg type
friend Arg get(s_get_one, std::integral_constant<std::size_t, Index>);
};
template < typename... Bases >
struct s_get : Bases... {};
}
template < std::size_t I, class T >
struct tuple_element;
template < std::size_t I, class... Args >
struct tuple_element < I, std::tuple<Args...> >
{
template<class T>
struct wrapper { using type = T; };
// deduce indices from seq helper
template < std::size_t... Is >
static auto helper(seq<Is...>)
-> detail::s_get< detail::s_get_one<Is, wrapper<Args>>... >;
// generate indices in O(log(N)) and use name lookup to find the type
using IC = std::integral_constant<std::size_t, I>;
using wrapped_type = decltype( get(helper(gen_seq<sizeof...(Args)>{}), IC{}) );
using type = typename wrapped_type::type;
};
Why C++11 was not added special operator for getting elements by index? like tuple2 or tuple[0] ?
First, because even if they did, it'd still work the same way: with recursion. Tuples are primarily a library feature. Though they piggy-back off of language features like variadic templates, they were more or less functional in C++98/03.
Second, that would not be possible. Not without a very difficult language change.
It's not clear what you mean by tuple[2].
If you mean that std::tuple<int, float, std::string>[2] should somehow resolve to the typename std::string, then that means you now need to explain why this works. Again, tuples are a library feature, not a language construct. So there would have to be some language construct whereby typename[integer] is a valid construct. What would that be and what would it mean?
If you mean that given:
std::tuple<int, float, std::string> tpl{...};
We should be able to get the string with tpl[2], that's several shades of "not going to happen". C++ is a statically typed language. The only reason std::get is able to get away with what it does is that the integer index is not a function parameter; it is a template parameter. That is what allows std::get<0> to return a completely different type from std::get<2>. That can't happen with operator[](int); that function must always return the same type.
So now you'd need to have something like template<class T, int i> ... operator[](). And that would be very confusing, because you can no longer do tpl[runtimeValue] on that type (since template parameters must be compile-time values). There is no such type where operator[] is restricted from being able to work on runtime values. So you'd be creating a very oddball type.
And even then... it would still have to do recursion to get the value.
Is possible reduce the deep instantiation?
Outside of compile times (which is not an unreasonable issue), what does it matter? A decent inliner will throw most of them away.
As for compile times, there are non-recursive implementations of various features of std::tuple. Whether they can do tuple_element non-recursively, I don't think so. This libc++ implementation seems to suggest that it can't, despite implementing the tuple itself non-recursively.
template< int ...i> struct seq{};
// GCC couldn't optimize sizeof..(i) ,
//see http://stackoverflow.com/questions/19783205/why-sizeof-t-so-slow-implement-c14-make-index-sequence-without-sizeof
//so I use direct variable `s` instead of it.
// i.e. s == number of variadic arguments in `I`.
template< int s, typename I, typename J > struct concate;
template< int s, int ...i, int ...j>
struct concate<s, seq<i...>, seq<j...> >
{
typedef seq<i..., (s + j)...> type;
};
template<int n> struct make_seq_impl;
template< int n> using make_seq = typename make_seq_impl<n>::type;
template<> struct make_seq_impl<0>{ typedef seq<> type;};
template<> struct make_seq_impl<1>{ typedef seq<0> type;};
template<int n> struct make_seq_impl: concate< n/2, make_seq<n/2>, make_seq<n-n/2>>{};
template< typename ...T> using seq_for = make_seq< sizeof...(T) > ;
//----------------------------------
template< int i, typename T> struct id{};
template< typename T> struct id<0,T>{ typedef T type;};
template< typename ...T> struct base : T ... {};
template< typename ...T> struct tuple{};
template< std::size_t i, typename Tuple> struct tuple_element;
template< std::size_t i, typename ...T>
struct tuple_element< i, tuple<T...> >
{
template< typename Seq > struct apply;
template< int ...j > struct apply< seq<j...> >
{
// j xor i ==> ( 0 xor i), (1 xor i), (2 xor i ),...(i xor i) ...
// => i0, i1, ..., 0 (at pos i) ...
// and only id<0,T> has `type`.
typedef base< id< (j xor i), T> ... > base_t;
typedef typename base_t::type type;
};
typedef typename apply< seq_for<T...> >::type type;
};

constexpr template functions don't see member array sizes as const expressions

Both clang and gcc fail to compile the code below when ArrayCount is a template. This seems wrong, especially in light of the fact that the sizeof ArrayCount solution work. The template version of ArrayCount is normally a better solution, but it's getting in the way here and constexpr is seemingly not living up to the spirit of its promise.
#if 1
template<typename T, size_t N>
constexpr size_t ArrayCount(T (&)[N])
{
return N;
}
// Results in this (clang): error : static_assert expression is not an integral constant expression
// Results in this (gcc): error: non-constant condition for static assertion, 'this' is not a constant expression
#else
#define ArrayCount(t) (sizeof(t) / sizeof(t[0]))
// Succeeds
#endif
struct X
{
int x[4];
X() { static_assert(ArrayCount(x) == 4, "should never fail"); }
};
The right solution doesn't use homebrew code, but a simple type trait:
int a[] = {1, 2, 3};
#include <type_traits>
static_assert(std::extent<decltype(a)>::value == 3, "You won't see this");
It makes sense to me that this code would fail to compile since ArrayCount is a function taking a non-constexpr argument. According to the standard, I believe this means that ArrayCount must be intstantiated as a non-constexpr function.
There are workarounds, of course. I can think of two off the top of my head (one implemented in terms of the other):
template<typename T> struct ArrayCount;
template<typename T, size_t N>
struct ArrayCount<T[N]> {
static size_t const size = N;
};
template<typename T>
constexpr size_t ArrayCount2() {
return ArrayCount<T>::size;
}
struct X {
int x[4];
X() {
static_assert(ArrayCount<decltype(x)>::size == 4, "should never fail");
static_assert(ArrayCount2<decltype(x)>() == 4, "should never fail");
}
};
It does mean having to use decltype() when you might not wish to, but it does break the pro-forma constraint on taking a non-constexpr parameter.

Resources