Reputation: 13850
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
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