我有一组模板类,我想放在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>
错误:模板参数列表中参数1的类型/值不匹配 对于'模板类std :: variant'
添加typename
似乎也不起作用。
答案 0 :(得分:3)
您无法使用std::variant
来执行此操作。您可以使用std::any
,但不能visit
any
。
问题是Type1
和Type2
不是类型,它们是类型模板。 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;