我们可以在编译时验证函数的输入是模板的专用化。I.E下面的代码验证f
的输入是structHolder的某种特殊化。
template<typename T>
struct Holder<T> {...};
template<typename T>
void f(Holder<T> h) {...};
我想验证一组可变参数是模板的特殊化。更确切地说,我想区分两个连续的变参数集——一个集是模板的专门化,另一个集不是。下面是一个例子,说明如果语法允许它-,它可能会是什么样子
template<...Args1, ...Args2>
void f(Holder<Args1>.... args_which_are_specializations_of_Holder, Args2... args_which_are_not) {
use_holders(args_which_are_specializations_of_Holder...);
use_rest(args_which_are_not...);
return;
}
这可能吗?
谢谢,
您可以将args
存储在tuple
中,并计算最后一个Holder
参数的索引,然后通过索引提取Holder
和正常参数,并将它们转发给相应的函数。
#include <tuple>
template<class T>
constexpr bool is_holder = false;
template<class T>
constexpr bool is_holder<Holder<T>> = true;
template<class... Args>
void f(Args... args) {
constexpr auto holder_index = (is_holder<Args> + ... + 0);
auto args_tuple = std::tuple(args...);
[&args_tuple]<auto... Is>(std::index_sequence<Is...>) {
use_holders(std::get<Is>(args_tuple)...);
}(std::make_index_sequence<holder_index>{});
[&args_tuple]<auto... Is>(std::index_sequence<Is...>) {
use_rest(std::get<Is + holder_index>(args_tuple)...);
}(std::make_index_sequence<sizeof...(Args) - holder_index>{});
}
演示
像这样混合可变参数更难。您可以使用std::tuple
:
#include <tuple>
#include <cstdio>
template<class T>
struct Holder {
T value;
};
template <class ...T1, class ...T2>
void f(const std::tuple<Holder<T1>...>& holders, const std::tuple<T2...>& non_holders) {
std::printf("Holder count: %zun"
"Non-holder count: %zun", sizeof...(T1), sizeof...(T1));
}
int main() {
Holder<int> a{};
Holder<double> b{};
int c{};
double d{};
f(std::tuple{a, b}, std::tuple{c, d});
}