Variadic Tuples Implementation - c++11

I've been trying to use Variadic Tuples on Generic Templates and Structs. The idea is to obtain the max and sum of a variadic tuple. So far I was able to obtain the required results but had to use Global static variables. I've posted the code below of the implementation.
#include <iomanip>
#include <complex>
#include <cmath>
#include <tuple>
#include <string>
#include <iostream>
using namespace std;
using namespace std::complex_literals;
template<typename T>
static T max;
template<typename T>
static T sum;
template<typename T>
static T average;
template <typename T, typename Tuple, std::size_t N>
struct Calculator
{
static void maximum(const Tuple& pack)
{
Calculator<T, Tuple, N - 1>::maximum(pack);
T packValue = get<N - 1>(pack);
if (packValue > max<T>)
{
//T max = get<0>(pack);
//Try the above instead of the below code to calculate max
max<T> = get<N - 1>(pack);
}
}
static void summation(const Tuple& pack)
{
Calculator<T, Tuple, N - 1>::summation(pack);
T packValue = get<N - 1>(pack);
sum<T> += packValue;
}
static void averager(const Tuple& pack)
{
average<T> = sum<T> / N;
}
};
template<typename T, typename Tuple>
struct Calculator<T, Tuple, 1>
{
static void maximum(const Tuple& pack)
{
//T max = get<0>(pack);
//Try the above instead of the below code to calculate max
max<T> = get<0>(pack);
}
static void summation(const Tuple& pack)
{
sum<T> = get<0>(pack);
}
};
int main()
{
tuple<double, double, double, double, double, double, double> t1 = make_tuple(16565.256, 45.539, 0.25, 1000.25, 1.25036, 35.66, 210.20);
Calculator<double, tuple<double, double, double, double, double, double, double>, 7>::maximum(t1);
cout << "Maximum is: " << max<double> << endl;
Calculator<double, tuple<double, double, double, double, double, double, double>, 7>::summation(t1);
cout << "Total Sum is: " << sum<double> << endl;
Calculator<double, tuple<double, double, double, double, double, double, double>, 7>::averager(t1);
cout << "Average is: " << average<double> << endl;
std::complex<int> c2(22, 3);
std::complex<int> ci(15, 41);
tuple<std::complex<int>, std::complex<int> > ct1 = make_tuple(ci, c2);
Calculator< std::complex<int>, tuple<std::complex<int>, std::complex<int> >, 2>::summation(ct1);
cout << "Summation of complex numbers is: " << sum<std::complex<int>> << endl;
}
My question, is it possible to implement a version that doesn't use Global static variables to hold the values of sum and max but an alternate implementation using Variadic Templates and Structs if possible?

You use variable template, so you have at least C++14. In C++14 you can use index_sequence as easy way to extract all tuple items and rewrite your recursion functions to be non-recursive:
template <typename T, typename Tuple, std::size_t N>
struct Calculator
{
template<size_t ... Indices>
static T maxHelper(const Tuple& pack, std::index_sequence<Indices...>) {
return std::max( {std::get<Indices>(pack)...} );
} // [1]
static T maximum(const Tuple& pack) {
return maxHelper(pack, std::make_index_sequence<N>{});
}
template<size_t ... Indices>
static T sumHelper(const Tuple& t, std::index_sequence<Indices...>) {
T arr[] = { std::get<Indices>(t)... }; // [2]
return std::accumulate(arr,arr+N,T{}); // [3]
}
static T summation(const Tuple& pack) {
return sumHelper(pack,std::make_index_sequence<N>{});
}
};
in [1] tuple's items are extracted into std::initializer_list, then std::max overload taking that list is called.
in [2] and [3] tuple's items are extracted into array, and summing is done by std::accumulate.
Demo
Since of C++17 use std::apply (and fold expression for summing):
template<class ... Args>
auto maxValue(std::tuple<Args...> t) {
return std::apply( [](auto&&... args) { return std::max({args...}); },t);
}
template<class ... Args>
auto sumValue(std::tuple<Args...> t) {
return std::apply( [](auto&&... args){ return (args + ...);} , t);
}
Demo

Related

Recursive indexing for tensor in C++11

I have a tensor classes of rank N which wrap data stored in an array. For example, a rank-3 tensor would have dimensions (d0,d1,d2) and a unique element would be accessed with the multi-index (i0,i1,i2) from the underlying array of length d0*d1*d2. If d0=d1=d2=10, i0=1, i1=2, i2=3, then element 123 of the array would be accessed.
I've implemented a recursively defined class which computes single array index from the multi-index as follows:
template<size_t N>
class TensorIndex : TensorIndex<N-1> {
private:
size_t d;
public:
template<typename...Ds>
TensorIndex( size_t d0, Ds...ds ) : TensorIndex<N-1>( ds... ), d(d0) {}
template<typename...Is>
size_t index( size_t i0, Is...is ) {
return i0+d*TensorIndex<N-1>::index(is...);
}
};
template<>
struct TensorIndex<1> {
TensorIndex( size_t ) {}
size_t index( size_t i ) { return i; }
};
Which reverses the desired order.
TensorIndex<3> g(10,10,10);
std::cout << g.index(1,2,3) << std::endl;
outputs 321. What would be a simple way to reverse the order of the arguments for the constructor and index functions?
Edit:
I tried implementing using the suggested approach of reversing the variadic arguments, but this was suboptimal as it required reversing the arguments for both index and the constructor and the necessary helper functions for these two cases would appear slightly different. The initializer list answer looks more straightforward.
No need of recursion nor to reverse, you can use initializer-list to call an evaluation function that accumulates index from left to right. The function object called in the initalizer-list should have a non-void return type :
#include <cstddef>
#include <iostream>
using namespace std;
template<size_t N>
class TensorIndex {
public:
template<typename... Args>
TensorIndex(Args... args) : dims{static_cast<size_t>(args)...}
{
static_assert(sizeof...(Args) == N,
"incorrect number of arguments for TensorIndex constructor");
}
template<typename... Args>
size_t index(Args... args) {
static_assert(sizeof...(Args) == N,
"incorrect number of arguments for TensorIndex::index()");
IndexEval eval{dims};
Pass pass{eval(args)...}; // evaluate from left to right : initializer-list
return eval.get_res();
}
private:
const size_t dims[N];
class IndexEval {
size_t k = 0;
size_t res = 0;
const size_t* dims;
public:
IndexEval(const size_t* dims) : dims{dims} {}
size_t operator()(size_t i) {
return res = res * dims[k++] + i;
}
size_t get_res() const { return res; }
};
struct Pass {
template<typename... Args> Pass(Args...) {}
};
};
int main()
{
TensorIndex<3> g(10, 10, 10);
cout << g.index(1, 2, 3) << endl;
}

Identify pointers in a tuple c++11

I need to convert a tuple to a byte array. This is the code I use to convert to byte array:
template< typename T > std::array< byte, sizeof(T) > get_bytes( const T& multiKeys )
{
std::array< byte, sizeof(T) > byteArr ;
const byte* start = reinterpret_cast< const byte* >(std::addressof(multiKeys) ) ;
const byte* end = start + sizeof(T);
std::copy(start, end, std::begin(byteArr));
return byteArr;
}
Here is how I call it:
void foo(T... keyTypes){
keys = std::tuple<T... >(keyTypes...);
const auto bytes = get_bytes(keys);
}
I need to augment this code such that when a pointer is a part of the tuple, I dereference it to it's value and then pass the new tuple, without any pointers, to the get_bytes() function. How do I detect the presence of a pointer in the tuple? I can then iterate through the tuple and dereference it with:
std::cout << *std::get<2>(keys) << std::endl;
Add a trivial overload: T get_bytes(T const* t) { return getBytes(*t); }.
That would be easy with C++14 :
#include <iostream>
#include <tuple>
#include <utility>
template <class T> decltype(auto) get_dereferenced_value(T &&value) {
return std::forward<T>(value);
}
template <class T> decltype(auto) get_dereferenced_value(T *value) {
return *value;
}
template <class Tuple, class Indexes> struct get_dereferenced_tuple_impl;
template <class... Args, size_t... Index>
struct get_dereferenced_tuple_impl<std::tuple<Args...>,
std::integer_sequence<size_t, Index...>> {
decltype(auto) operator()(std::tuple<Args...> const &originalTuple) {
return std::make_tuple(
get_dereferenced_value(std::get<Index>(originalTuple))...);
}
};
template <class Tuple>
decltype(auto) get_dereferenced_tuple(Tuple const &tupleValue) {
return get_dereferenced_tuple_impl<
Tuple,
std::make_integer_sequence<size_t, std::tuple_size<Tuple>::value>>{}(
tupleValue);
}
int main() {
char c = 'i';
std::tuple<char, char *> t{'h', &c};
auto t2 = get_dereferenced_tuple(t);
std::cout << std::get<0>(t2) << std::get<1>(t2) << "\n";
return 0;
}
If you cannot use C++14, then you would have to write more verbose decltype expressions, as well as include an implementation of std::(make_)integer_sequence.
This has a drawback though : copies will be made before copying the bytes. A tuple of references is not a good idea. The most performant version would be a get_bytes able to serialize the entire mixed tuple directly.

C++ - variadic template partial specialization

Let's have a simple snippet:
template<class T, class... Args>
struct A {
void operator()() { std::cout << "A"; }
};
template<class T, class... Args>
struct A<T, double, Args...> {
void operator()() { std::cout << "B"; }
};
template<class T, class B, class... Args>
struct A<T, B, double, Args...> {
void operator()() { std::cout << "C"; }
};
Which i can use in this way:
int main() {
A<int, int, int> a;
A<int, double, int> b;
A<int, int, double> c;
a(); b(); c();
return 0;
}
It properly returns "ABC". But when i declare A<int, double, double> d; i get obviously compile time error ambiguous class template instantiation for struct A<int, double, double>.
The question is: can i do some trick (probably using SFINAE) to take into account the second template argument as it would have a higher priority and specialization returning B would be used? (Ignoring type double on third position)
NOTE: types double and int are used to make example simpler, i will use type traits. And therefore i would like to avoid following specialization as a solution:
template<class T, class... Args>
struct A<T, double, double, Args...> {
void operator()() { std::cout << "D"; }
};
As you suggest, you can use SFINAE to not consider the C specialization if the second template argument is double:
template<typename, class T, class... Args>
struct A_impl {
void operator()() { std::cout << "A"; }
};
template<class T, class... Args>
struct A_impl<void, T, double, Args...> {
void operator()() { std::cout << "B"; }
};
template<class T, class B, class... Args>
struct A_impl<typename std::enable_if<!std::is_same<B,double>::value>::type,
T, B, double, Args...> {
void operator()() { std::cout << "C"; }
};
template<class T,class... Args>
using A = A_impl<void,T,Args...>;

Fusion adaped std_tuple views, conversion to another tuple

Boost Fusion has been designed in such a way that most of the transformations are "lazy", in the sense that they all generate "views" but not actual (Fusion) containers (http://www.boost.org/doc/libs/1_58_0/libs/fusion/doc/html/fusion/algorithm.html). So for example to actually reverse a vector one needs to use the conversion function as_vector (http://www.boost.org/doc/libs/1_58_0/libs/fusion/doc/html/fusion/container/conversion/functions.html).
boost::fusion::vector<int, double, std::string> vec;
auto view_rev = boost::fusion::reverse(vec); // view object
auto vec_rev = boost::fusion::as_vector(view_rev);
Now, I want to do this with adapted std::tuple:
#include<boost/fusion/adapted/std_tuple.hpp>
...
std::tuple<int, double, std::string> tup;
auto view_rev = boost::fusion::reverse(tup);
auto tup_rev = boost::fusion::???(view_rev); // type should be of type std::tuple<std::string, double, int>
How do I convert the resulting view back to a tuple?
I expected this ??? function to be called as_std_tuple (in analogy to boost::fusion::as_vector, but it doesn't exists (yet?).
There a few solutions for reversing tuples, in this case I want just to use what is already in Boost Fusion.
I am not aware of any built-in method to convert a Boost Fusion Sequence into a std::tuple, but using the indices trick it can be implemented rather easily:
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename Sequence, std::size_t ...Is>
auto as_std_tuple_impl(const Sequence& s, indices<Is...>&&) -> decltype(std::tie(boost::fusion::at_c<Is>(s)...))
{
return std::tie(boost::fusion::at_c<Is>(s)...);
}
template <typename Sequence, typename Indices = build_indices<boost::fusion::result_of::size<Sequence>::value>>
auto as_std_tuple(const Sequence& s) -> decltype(as_std_tuple_impl(s, Indices()))
{
return as_std_tuple_impl(s, Indices());
}
Here is a full example that reverses an adapted std::tuple using boost::fusion::reverse and converts it back into a std::tuple and prints both tuples:
#include <tuple>
#include <utility>
#include<boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/transformation/reverse.hpp>
#include <boost/fusion/include/reverse.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/size.hpp>
#include <iostream>
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename Sequence, std::size_t ...Is>
auto as_std_tuple_impl(const Sequence& s, indices<Is...>&&) -> decltype(std::tie(boost::fusion::at_c<Is>(s)...))
{
return std::tie(boost::fusion::at_c<Is>(s)...);
}
template <typename Sequence, typename Indices = build_indices<boost::fusion::result_of::size<Sequence>::value>>
auto as_std_tuple(const Sequence& s) -> decltype(as_std_tuple_impl(s, Indices()))
{
return as_std_tuple_impl(s, Indices());
}
template<class Tuple, std::size_t N>
struct TuplePrinter
{
static void print(const Tuple& t)
{
TuplePrinter<Tuple, N-1>::print(t);
std::cout << ", " << std::get<N-1>(t);
}
};
template<class Tuple>
struct TuplePrinter<Tuple, 1>
{
static void print(const Tuple& t)
{
std::cout << std::get<0>(t);
}
};
template<class... Args>
void print(const std::tuple<Args...>& t)
{
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")\n";
}
int main()
{
std::tuple<int, double, std::string> tup(1,2.5,"hello");
auto view_rev = boost::fusion::reverse(tup);
auto reversed_tup = as_std_tuple(view_rev);
print(tup);
print(reversed_tup);
return 0;
}
output:
(1, 2.5, hello)
(hello, 2.5, 1)
Live example on ideone

Ambiguous operator<< selection

I have some code which, very much simplified, looks somewhat like this:
#include <iostream>
#include <type_traits>
namespace X {
struct Foo {int x;};
struct Bar {int x;};
template <typename T , typename = typename std::enable_if<
std::is_same<decltype(T::x),int>::value
>::type>
std::ostream & operator<<(std::ostream & os, const T&) {
return os;
}
}
namespace Y {
struct Faa : X::Foo {int y;};
struct Baz {int x; int y;};
template <typename T , typename = typename std::enable_if<
std::is_same<decltype(T::x),int>::value &&
std::is_same<decltype(T::y),int>::value
>::type>
std::ostream & operator<<(std::ostream & os, const T&) {
return os;
}
}
int main() {
// Everything is ok
X::Foo x;
std::cout << x;
Y::Baz k;
std::cout << k;
// Problems..
Y::Faa y;
// std::cout << y; // <--operator is ambiguous
Y::operator<<(std::cout, y);
return 0;
}
Is there any way to avoid the ambiguous operator for Y::Faa and having to manually specify Y::operator<<? If not, why?
Two functions have a conflict because conditions on their arguments have non-empty intersection (actually, 1st supersedes 2nd). Function overloading works only if signatures are different. So, to solve this we have 2 options:
Change conditions so that they have empty intersection (manually forbid having y field by adding && !sfinae_has_member_y<T>::value condition to the 1st enable_if)
template<typename T>
struct sfinae_has_member_y {
static int has(...);
template<typename U = T, typename = decltype(U::y)>
static char has(const U& value);
enum { value = sizeof(char) == sizeof(has(std::declval<T>())) };
};
OR use another C++ feature that supports arguments overlapping, like struct/class template specialization. If you replace bool with int, other fields may be added too:
template<typename T, bool>
struct Outputter {
};
template<typename T>
struct Outputter<T, false> {
static std::ostream & output(std::ostream & os, const T&) {
os << "x";
return os;
}
};
template<typename T>
struct Outputter<T, true> {
static std::ostream & output(std::ostream & os, const T&) {
os << "y";
return os;
}
};
template<typename T, typename = std::enable_if_t<std::is_same<decltype(T::x), int>::value>>
std::ostream & operator<<(std::ostream & os, const T& a) {
return Outputter<T, sfinae_has_member_y<T>::value>::output(os, a);
}

Resources