如何检查模板参数是否为std::variant?

5

我想编写自己的容器MyContainer。它实现了一个emplace方法,以便在容器内就地构造对象。

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

虽然我希望始终返回Allocator类型。但是,如果模板参数Tstd::variant类型,则会出现问题。我想进行一种SFINAE,选择与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
}

我知道编译器可以根据我是否提供Allocator模板参数来选择重载。但是我想为我的容器创建一个适用于特定类型的子类型的emplace方法,而不仅仅是std::variant/union类型。所以我不希望得到那种答案。

1个回答

14

这是一个使用特化来展开模板类型的相当基础的案例:

#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;
}

这是你的基本蓝图。在模板中,你可以使用它,也许在一个if constexpr中执行适当的逻辑。或将其用作更复杂专业化的构建块。


非常好用!感谢您的回答!您为我节省了宝贵的时间。 - einstein
请问您能否加上一些解释呢?为什么当只有一个参数时是false_type,而当有多个参数时是true_type?在示例中每次只传递了一个参数。 - neshkeev
1
这被称为“模板特化”。请参阅您的C++教材中有关特化模板的解释。 - Sam Varshavchik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接