我正在尝试编写一个处理程序类,当给定一个元组时,它可以动态处理给定元组中的特定字段。
问题是,我不知道如何创建该类的实例,因为该类是模板化的,实例化所需的模板位于元组内。
(由于与问题无关的设计请求,将处理程序置于单独的类中非常重要)
请注意???
实例中的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;
}
重要提一下:使用未包含在类中的函数解决问题很容易,但是,我需要提供一个抽象类,以便用户必须自己实现该函数。
答案 0 :(得分:3)
作为一种可能的解决方案,您可以使用支持假函数,如下所示:
#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;
}
答案 1 :(得分: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;
}