einstein
einstein

Reputation: 13850

How to check if template argument is std::variant?

I want to write my own container MyContainer. Which implements an emplace method to construct objects in place.

template<typename T>
MyContainer<T>::emplace(Args ... args)
{
     // Some construction code ....
     *_cursor = T(args...);
     _cursor++;
     return *item;
}

Though, I want to always return the Allocator type. Though this becomes a problem if the the template argument T is of type std::variant. I would like to do an SFINAE that chooses the overload that fits one with std::variant.

template<typename T>
template<typename Allocator, typename ... Args>
Allocator&
MyContainer<T>::emplace(Args ... args)
{
     // Some construction code ....
     *_cursor = T(Allocator(args...)); // T is std::variant, Allocator is one variant of T.
     T* item = _cursor;
     _cursor++;
     return std::get<Allocator>(*item); // Here I want to return the correct variant
}

(I know the compiler could choose the overload based on if I provide the Allocator template arg or not. But I would like to create my container to have an emplace method for sub types of a particular type as well not just std::variant/union types. So I'm not look for those sort of answers).

Upvotes: 7

Views: 2325

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

This is a fairly basic case of using specialization to unravel a template type:

#include <variant>
#include <type_traits>
#include <iostream>
#include <string>

template<typename T> struct is_variant : std::false_type {};

template<typename ...Args>
struct is_variant<std::variant<Args...>> : std::true_type {};

template<typename T>
inline constexpr bool is_variant_v=is_variant<T>::value;

int main()
{

    std::cout << is_variant_v<int> << std::endl;

    std::cout << is_variant_v<std::string> << std::endl;

    std::cout << is_variant_v<std::variant<int, double>> << std::endl;
    return 0;
}

That's your basic blueprint. In a template you can use this, perhaps in an if constexpr to execute the appropriate logic. Or use this as a building block for a more complicated specialization.

Upvotes: 15

Related Questions