【问题标题】:Instantiation of a variadic template class when given an std::tuple<T...>?给定 std::tuple<T...> 时,可变参数模板类的实例化?
【发布时间】:2016-07-17 11:22:15
【问题描述】:

我正在尝试编写一个处理程序类,当给定一个元组时,它可以动态处理给定元组中的特定字段。

问题是,我不知道如何创建该类的实例,因为该类是模板化的,而实例化所需的模板在元组内。

(由于与问题无关的设计请求,将处理程序放在单独的类中很重要)

注意ILevelHandler 实例中的???,我需要提供模板,但我不知道该怎么做。

#include <tuple>
#include <string>
#include <iostream>
#include <boost/variant.hpp>

template <typename... T>
class ILevelHandler
{
public:
    virtual void HandleEnterLevel(const boost::variant<T...>& _value)
    {
        std::cout << " value: " << _value << std::endl;
    }   
};

int main()
{
    std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
    ILevelHandler<???> lvl(tpl);
    for (size_t i = 0; i < 4; ++ i)
    {
        lvl.HandleEnterLevel(i, dynamic_get(i, tpl));
    }
    return 0;
}

值得一提的是:使用未封装在类中的函数来解决问题很容易,但我需要提供一个抽象类,以便用户必须自己实现该函数。

【问题讨论】:

  • 您已经证明不需要将包编码为 ILevelHandler 的类型 - struct ILevelHandler { template&lt;typename... T&gt; void HandleEnterLevel(boost::variant&lt;T...&gt; const&amp; v) { std::cout &lt;&lt; " value: " &lt;&lt; v &lt;&lt; '\n'; } }; 有什么问题?
  • 没什么问题,其实好像是个解决办法。
  • 我会纠正自己 - 这不是一个解决方案,因为“ILevelHandler”函数应该是虚拟的,因此不能是模板函数。

标签: c++ templates c++11 tuples variadic-templates


【解决方案1】:

作为一种可能的解决方案,您可以使用支持假功能,如下所示:

#include <tuple>
#include <string>

template <typename... T>
class ILevelHandler {
public:
    ILevelHandler(const std::tuple<T...> &) {}
};

template<typename... T>
auto f(const std::tuple<T...> &) -> ILevelHandler<T...>;

int main() {
    std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
    decltype(f(tpl)) lvl(tpl);
    return 0;
}

请注意,您不需要定义函数f,像上面示例中的简单声明就足够了。
您还可以使用几个 using 声明来清理您的声明:

// ...

template<typename T>
using MyILevelHandler = decltype(f(std::declval<T>()));

// ...

int main() {
    using MyTuple = std::tuple<int, float, std::string, int>;

    MyTuple tpl {4, 6.6, "hello", 7};
    MyILevelHandler<MyTuple> lvl(tpl);
    return 0;
}

【讨论】:

    【解决方案2】:

    假设您已经编写了dynamic_get(假设您需要帮助),那么一个简单的转换类应该可以做到:

    #include <tuple>
    #include <string>
    #include <iostream>
    #include <boost/variant.hpp>
    
    template <typename... T>
    class ILevelHandler
    {
    public:
        void HandleEnterLevel(const boost::variant<T...>& _value)
        {
            std::cout << " value: " << _value << std::endl;
        }
    };
    
    template<class Thing>
    struct to_variant;
    
    template<class...T>
    struct to_variant<std::tuple<T...>>
    {
        using type = boost::variant<T...>;
    };
    
    template<class T> using to_variant_t = typename to_variant<T>::type;
    
    
    int main()
    {
        std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
        using tuple_type = decltype(tpl);
        using variant_type = to_variant_t<tuple_type>;
        ILevelHandler< variant_type > lvl;
        for (size_t i = 0; i < 4; ++ i)
        {
            lvl.HandleEnterLevel(i, dynamic_get(i, tpl));
        }
        return 0;
    }
    

    【讨论】:

    • 我可能弄错了,但这没有用。
    • @HaggaiMagen 我有一个错字 - 已修复
    猜你喜欢
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2013-10-28
    • 2020-04-07
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    相关资源
    最近更新 更多