c++ - 在 std::variant 中隐藏模板参数

标签 c++ c++17

我有一组模板类,我想将它们放入 std::variant 中。下面的工作,但相当丑陋(我在变体中有更多的类,有很多模板参数)。

template <typename T>
struct Type1
{ };

template <typename B, typename C>
struct Type2
{ };

template <typename A, typename B, typename C>
using Variant = std::variant<Type1<A>, Type2<B,C>>;

是否可以用类似的方式“隐藏”模板参数? (不编译)

template <typename A>
using Type1T = Type1<A>

template <typename B, typename C>
using Type2T = Type2<B, C>

using Variant = std::variant<Type1T, Type2T>

error: type/value mismatch at argument 1 in template parameter list for 'template class std::variant'

添加 typename 似乎也不起作用。

最佳答案

您不能使用 std::variant要做到这一点。您可以使用 std::any , 但你不能 visit一个any .

问题是 Type1Type2 不是类型,它们是类型模板Type1 的实例化无穷 , 就 visit 而言,它们都是不相关的类型很关心。

我建议你制作非模板Type1Base你得出Type1<T>来自,并拥有一个std::variant<std::unique_ptr<Type1Base>, std::unique_ptr<Type2Base>, ...>

编辑 - 甚至 template_variant不可能,无法恢复所选模板的哪个实例是事件成员。如果那是可能的,那么您会遇到这样的复杂情况,即每个 访问者都必须对每个 模板的每个 实例进行重载。

原始尝试:

您可以编写自己的模板变体,其中包含类似于 std::any 的成员组合和 std::variant

template<template<class...> class ... Templates>
class template_variant
{
    std::any value;
public:
  // constructors, operator=, etc

  // Observers
    constexpr std::size_t index() const noexcept; // Which template this contains
    const std::type_info& type() const noexcept; // returns the typeid of the contained value

 // Modifiers
    template <template<typename...> class T, class... Args>
    T<Args...>& 
    emplace(Args&&... args)
    {
         value.emplace<T<Args...>>(std::forward<Args>(args)...);
    }

    template <size_t I, class... Args>
    template_variant_alternative_t<I, variant, Args...>& 
    emplace(Args&&... args)
    {
         value.emplace<template_variant_alternative_t<I, variant, Args...>>(std::forward<Args>(args)...);
    }

    void swap( template_variant& rhs ) noexcept;

  // Non-member functions
    friend template <std::size_t I, template<class...> class ... Templates, class... Args>
    constexpr template_variant_alternative_t<I, template_variant<Templates...>, Args...>& 
    std::get(template_variant<Templates...>& v)
    {
        try 
        {
            return std::any_cast<template_variant_alternative_t<I, template_variant<Templates...>, Args...>&>(v.value);
        }
        catch (std::bad_any_cast & e)
        {
            throw bad_template_variant_access(e);
        }
    }
    // and &&, and const&, and const&&

    template <template<class...> class T, template<class...> class ... Templates, class... Args>
    constexpr T<Args...>& 
    std::get(template_variant<Templates...>& v)
    {
        try 
        {
            return std::any_cast<T<Args...>&>(v.value);
        }
        catch (std::bad_any_cast & e)
        {
            throw bad_template_variant_access(e);
        }
    }
    // and &&, and const&, and const&&

    // etc.
};

template <std::size_t I, typename Variant, class... Args>
struct template_variant_alternative;

template <std::size_t I, template<class...> class ... Templates, class... Args>
struct template_variant_alternative<I, template_variant<Templates...>, Args...>
{
    using type = // apply Args... to Ith template in Templates
};

template <std::size_t I, typename Variant, class... Args>
using template_variant_alternative_t = template_variant_alternative<I, Variant, Args...>::type;

关于c++ - 在 std::variant 中隐藏模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49669750/

相关文章:

c++ - 如何使用 QSettings 保存和加载数据?

c++ - 是否可以使用 std::filesystem 获取根名称列表?

c++ - 了解复制初始化和隐式转换

c++ - 递归地在干草堆中查找针的索引。

C++将索引器运算符添加到现有类而不进行修改

c++ - 从应用程序启动 Java 时在 MFC 应用程序中显示等待光标,直到它完成其进程

c++ - 检测图像中的点并进行比较

c++ - 一个函数可以返回一个指向它自己类型的指针吗?

c++ - 仅当没有其他转换可用时如何启用构造函数模板?

c++ - C++ 标准的哪一部分阻止显式指定此模板的参数?