Ker*_*g73 6 c++ variadic-functions variadic-templates c++17
我正在尝试创建一个带有两个对象参数包的函数。有两个模板化基类,我想将派生类的实例传递给此函数。考虑这个例子。
template <int N>
struct First {};
template <int N>
struct Second {};
// there are a few of these
struct FirstImpl : First<5> {};
struct SecondImpl : Second<7> {};
template <int... firstInts, int... secondInts>
void function(float f, First<firstInts> &... first, Second<secondInts> &... second) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
我想做的就是function
像这样打电话
FirstImpl firstImpl;
OtherFirstImpl otherFirstImpl;
SecondImpl secondImpl;
OtherSecondImpl otherSecondImpl;
function(9.5f, firstImpl, otherFirstImpl, secondImpl, otherSecondImpl);
Run Code Online (Sandbox Code Playgroud)
但这个例子无法编译。编译器似乎试图将所有内容打包到第二个参数包中,但由于FirstImpl
无法隐式转换而失败Second<N>
。
我该如何解决这个问题?
让我们首先编写一个变量模板来确定类型是否派生自First
:
template <int N>
constexpr std::true_type is_first(First<N> const &) { return {}; }
template <int N>
constexpr std::false_type is_first(Second<N> const &) { return {}; }
template <class T>
constexpr bool is_first_v = decltype( is_first(std::declval<T>()) )::value;
Run Code Online (Sandbox Code Playgroud)
以及一个收集和 的Split
索引的结构First
Second
结构:
template <class, class, class, std::size_t I = 0> struct Split;
template <
std::size_t... FirstInts,
std::size_t... SecondInts,
std::size_t N
>
struct Split<
std::index_sequence<FirstInts...>,
std::index_sequence<SecondInts...>,
std::tuple<>,
N
> {
using firsts = std::index_sequence<FirstInts...>;
using seconds = std::index_sequence<SecondInts...>;
};
template <
std::size_t... FirstInts,
std::size_t... SecondInts,
std::size_t I,
typename T,
typename... Tail
>
struct Split<
std::index_sequence<FirstInts...>,
std::index_sequence<SecondInts...>,
std::tuple<T, Tail...>,
I
> : std::conditional_t<
is_first_v<T>,
Split<std::index_sequence<FirstInts..., I>,
std::index_sequence<SecondInts...>,
std::tuple<Tail...>,
I + 1
>,
Split<std::index_sequence<FirstInts...>,
std::index_sequence<SecondInts..., I>,
std::tuple<Tail...>,
I + 1
>
> {};
Run Code Online (Sandbox Code Playgroud)
就像我在评论中告诉你的那样,value
向First
and添加成员Second
(或从 继承std:integral_constant
),这允许我们编写以下内容:
template <std::size_t... FirstIdx, std::size_t... SecondIdx, typename Tuple>
void function_impl(float f, std::index_sequence<FirstIdx...>, std::index_sequence<SecondIdx...>, Tuple const & tup) {
((std::cout << "firstInts: ") << ... << std::get<FirstIdx>(tup).value) << '\n';
((std::cout << "secondInts: ") << ... << std::get<SecondIdx>(tup).value) << '\n';
// your implementation
}
template <class... Args>
void function(float f, Args&&... args) {
using split = Split<std::index_sequence<>,std::index_sequence<>, std::tuple<std::decay_t<Args>...>>;
function_impl(f, typename split::firsts{}, typename split::seconds{}, std::forward_as_tuple(args...));
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5394 次 |
最近记录: |