使用带有模板推导的增强变体
Using boost variant with template deduction
考虑以下 class:
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;
}
};
并创建 class 的实例:
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>> &'
看起来它不能隐式地将函数类型转换为该函数类型的变体?这似乎没有矢量效果更好,但我不应该仍然能够做到这一点吗?
谢谢,
瑞安
即使 A
可以转换为 B
,std::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)...});
}
}
并创建 class 的实例:
using class_type = myClass<SomeOtherClass>;
auto vec = class_type::make_vtable(&SomeOtherClass::someFunc, &SomeOtherClass::someOtherFunc);
auto classInstance = class_type(vec);
你可以拿 initializer_list
的 FunctionVariantType
:
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
.
的构造函数
考虑以下 class:
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;
}
};
并创建 class 的实例:
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>> &'
看起来它不能隐式地将函数类型转换为该函数类型的变体?这似乎没有矢量效果更好,但我不应该仍然能够做到这一点吗?
谢谢,
瑞安
即使 A
可以转换为 B
,std::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)...});
}
}
并创建 class 的实例:
using class_type = myClass<SomeOtherClass>;
auto vec = class_type::make_vtable(&SomeOtherClass::someFunc, &SomeOtherClass::someOtherFunc);
auto classInstance = class_type(vec);
你可以拿 initializer_list
的 FunctionVariantType
:
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
.