Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an std::variant that holds all variants

Tags:

c++

templates

I am looking for a class that is like std::variant that holds all types instead of one of the types.

So I would like to be able to write:

std::all_variant<int, double> av{1, 3.14159};
int i = std::get<int>(av); // i should be 1.
double d = std::get<double>(av); // d should be 3.14159

This is basically a tuple but guarantees that each type appears only once so you can do std::get<Type> instead of std::get<Index>.

For context I want to be able to write the following code (so if there is a better way of doing that I would appreciate to know):

std::all_variant<int, double> av{1, 3.14159};

template <typename T> // T must be either int or double.
void MyFunc(std::all_variant<int, double> av) {
  std::cout << std::get<T>(av);
}

int main() {
  MyFunc<int>(av); // Should print 1.
  MyFunc<double>(av); // Should print 3.14159.
  MyFunc<std::string>(av); // Error! av doesn't have std::string variant. 
}

I'm not sure what this would be called so I'm not sure if this is in the standard library. I guess it wouldn't be to hard to write one but I don't want to reinvent the wheel.

like image 775
Benjy Kessler Avatar asked Oct 20 '20 17:10

Benjy Kessler


2 Answers

I am looking for a class that is like std::variant that holds all types instead of one of the types.

What you are looking for is called std::tuple

std::tuple<int,double> mytup( 1, 2.0 );
std::cout << std::get<int>( mytup ) << "\n"; // prints 1
std::cout << std::get<double>( mytup ) << "\n"; // prints 2
std::cout << std::get<std::string>( mytup ) << "\n"; // compiler error

Live example

As for single type appearance requirement you would get compilation error when you try to use std::get<type> instead of index with std::tuple with duplicated types. (thanks @max66)

like image 125
Slava Avatar answered Oct 19 '22 23:10

Slava


In addition to Slava's answer, you can enforce type-uniqueness in a tuple using for example something like is_unique from this post:

#include <tuple>
#include <type_traits>

// From https://stackoverflow.com/a/47511516
template <typename...>
inline constexpr auto is_unique = std::true_type{};

template <typename T, typename... Rest>
inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
    (!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
>{};  

// Tuple that only accept unique type parameters
template<typename... Ts>
using uniq_tuple = typename std::enable_if<is_unique<Ts...>, std::tuple<Ts...>>::type;

int main()
{
    // Compiles
    uniq_tuple<int, float> t1;
    // Fails
    uniq_tuple<int, float, int> t2;
    return 0;
}
like image 25
jdehesa Avatar answered Oct 20 '22 01:10

jdehesa