为使用数组、向量、结构等传递给可变参数函数或可变参数模板函数的所有参数指定一种类型?
这个问题是关于保证所有参数都是相同类型的,同时表现出带有干净编译器错误的早期拒绝行为,而不是模板乱码
我正在创建一个需要接受未知数量参数的函数(可能是成员函数,这并不重要……也许确实如此?),但我希望它们都是相同的类型.我知道我可以传入一个数组或向量,但我希望能够直接接受 args 列表,而无需额外的结构甚至额外的括号.看起来可变参数函数本身并不是类型安全的,而且我不确定如何使用可变参数模板函数来处理这个问题.这基本上就是我的目标(很可能不是正确的代码,而且完全不是为了获取龙的列表,哈哈):
I'm creating a function (possibly member function, not that it matters... maybe it does?) that needs to accept an unknown number of arguments, but I want all of them to be the same type. I know I could pass in an array or vector, but I want to be able to accept the list of args directly without extra structure or even extra brackets. It doesn't look like variadic functions by themselves are typesafe, and I wasn't sure how to go about this w/ variadic template functions. Here's essentially what I'm aiming for (more than likely not correct code, and totally not for the purpose of getting lists of dragons, lol):
//typedef for dragon_list_t up here somewhere.
enum Maiden {
Eunice
, Beatrice
, Una_Brow
, Helga
, Aida
};
dragon_list_t make_dragon_list(Maiden...) {
//here be dragons
}
或
template<Maiden... Maidens> dragon_list_t make_dragon_list(Maidens...) {
//here be dragons
}
用法
dragon_list_t dragons_to_slay
= make_dragon_list(Maiden.Eunice, Maiden.Helga, Maiden.Aida)
;
已经尝试了一些与上述类似的事情,没有骰子.建议?我可能做了明显的疏忽?我知道这样做可能没什么大不了的:
Tried a few things similar to the above already, no dice. Suggestions? Obvious oversights I may have made? I know it may not be a huge deal to do this instead:
dragon_list_t make_dragon_list(std::array<Maiden> maidens) {
//here be dragons.
}
dragon_list_t dragons_to_slay
= make_dragon_list({Maiden.Eunice, Maiden.Helga, Maiden.Aida})
;
但如果可能的话,我更愿意采用第一种方式.
but I'd much rather be able to do it the first way if possible.
推荐答案
您可以只接受可变参数模板的参数,并让类型检查在稍后转换它们时检查其有效性.
You can just accept the arguments by the variadic template and let typechecking check the validity later on when they are converted.
不过,您可以在函数接口级别检查可转换性,以利用重载解析来拒绝完全错误的参数,例如,通过使用 SFINAE
You can check convertibility on the function interface level though, to make use of overload resolution for rejecting outright wrong arguments for example, by using SFINAE
template<typename R, typename...> struct fst { typedef R type; };
template<typename ...Args>
typename fst<void,
typename enable_if<
is_convertible<Args, ToType>::value
>::type...
>::type
f(Args...);
对于您的用例,如果您知道从 std::array<>
到 dragon_list_t
的步骤,那么您已经根据上面的第一个选项(稍后转换"):
For your use-case if you know the steps to go from an std::array<>
to your dragon_list_t
then you have already solved it though according to the first option above ("convert-later"):
template<typename ...Items>
dragon_list_t make_dragon_list(Items... maidens) {
std::array<Maiden, sizeof...(Items)> arr = {{ maidens ... }};
// here be dragons
}
如果您将其与上述 is_convertible
方法结合使用,您将获得一个拒绝早期模板,该模板也对参数进行重载解析,并在不适用时拒绝它们.
If you combine this with the above is_convertible
approach you have a reject-early template that also does overload resolution on arguments and rejects them if not applicable.
相关文章