使用带有模板推导的boost变体

Using boost variant with template deduction

本文关键字:boost 变体      更新时间:2024-04-27

考虑以下类:

template <typename classTypeT>
class myClass {
public:    
using FunctionType1 = std::function<void(classTypeT &, const std::string*)>;
using FunctionType2 = std::function<void(classTypeT &, const int)>;
using FunctionVariantType = boost::variant<FunctionType1, FunctionType2>;
std::vector<FunctionVariantType> myVariants;
myClass(const std::vector<FunctionVariantType> myVec) {
myVariants = myVec;
}
};

并创建该类的实例:

auto vec = std::vector<myClass<SomeOtherClass>::FunctionVariantType>({&SomeOtherClass::someFunc});
auto classInstance = myClass<SomeOtherClass>(vec);

这段代码很好用,可以实现我想要的功能,但我真的希望避免在向量中指定模板类型。也就是说,我希望能够做到这一点:

auto vec = std::vector({&SomeOtherClass::someFunc});
auto classInstance = myClass<SomeOtherClass>(vec); // Error

有一些模板分离,但我得到了一个这样的错误:

cannot convert argument 1 from 'std::vector<void (__cdecl myClass::* )(const std::string *),std::allocator<_Ty>>' to 'const std::vector<mwboost::variant<std::function<void (classTypeT &,const std::string *)>,std::function<void (classTypeT &, const int)>>,std::allocator<_Ty>> &'

看起来它不能将函数类型隐式转换为该函数类型的变体?这似乎在没有矢量的情况下效果更好,但我不应该还能做到吗?

谢谢,

Ryan

您可以获取FunctionVariantType:的initializer_list

template <typename T>
class myClass {
public:
using FunctionType1 = std::function<void(T&, const std::string*)>;
using FunctionType2 = std::function<void(T&, const int)>;
using FunctionVariantType = std::variant<FunctionType1, FunctionType2>;
std::vector<FunctionVariantType> myVariants;
myClass(std::initializer_list<FunctionVariantType> myVec)
: myVariants(myVec) {}
};
int main()
{
auto func1 = [](int&, const std::string*) {};
auto func2 = [](int&, const int) {};
myClass<int> myInst({func1, func2});
}

这是因为vector也有一个采用initializer_list的构造函数。

即使A可转换为Bstd::vector<A>也不能转换为std::vector<B>

但是您可以使用迭代器构造函数从std::vector<A>轻松地构造std::vector<B>

auto vec = std::vector({&SomeOtherClass::someFunc});
auto classInstance = myClass<SomeOtherClass>({vec.begin(), vec.end()});

如果你绝对必须通过中间vec变量,那么我认为解决这个问题的最好方法是用手握住编译器一点,并引导它完成整个过程。

在你的具体情况下,我会按照以下一般路线进行:


template <typename classTypeT>
class myClass {
public:
[...]
template<typename... Args>
static auto make_vtable(Args&&... args) {
return std::vector<FunctionVariantType>({std::forward<Args>(args)...});
}
}

并创建类的实例:

using class_type = myClass<SomeOtherClass>;
auto vec = class_type::make_vtable(&SomeOtherClass::someFunc, &SomeOtherClass::someOtherFunc);
auto classInstance = class_type(vec);