可变 class 成员(元组或其他)的参数包扩展
Parameter pack expansion for variadic class member (tuple or other)
我试图在 class 中存储一个引用元组(通过可变参数模板),然后我想“循环”它们并为它们赋值。
下面的函数 process2
按预期工作,但我想让函数 process1
工作相同(利用 class 本身的存储引用)。但是,我无法使 process1
编译。什么是正确的方法?有没有办法让成员 Args&... args;
而不是 std::tuple<Args&...> args
(因为这可能允许参数扩展)?任何建议表示赞赏。
示例代码:
#include <tuple>
#include <string>
#include <iostream>
template<class... Args>
class Handler
{
private:
template <class T>
static bool process_arg(T& val)
{
if constexpr (std::is_same_v<T, int>)
val = 123;
else if constexpr (std::is_same_v<T, std::string>)
val = "string";
else
{
// do something
return false;
}
return true;
}
public:
const std::tuple<Args&...> args;
Handler(Args&... args)
: args(args ...) { }
// bool process1() const
// {
// // Compile Error: operand of fold expression has no unexpanded parameter packs
// const bool success = (process_arg(args) && ...);
// // Compile Error: no matching function for process_arg(int&, int&, std::string&)
// bool success = true;
// std::apply([&success](auto &&... v) { success = success && process_arg(v...); }, args);
// return success;
// }
template<class... Args2>
static bool process2(Args2&... args2)
{
const bool success = (process_arg(args2) && ...);
return success;
}
};
int main()
{
int a, b;
std::string c;
// Handler(a, b, c).process1();
Handler<>::process2(a, b, c);
std::cout << a << "," << b << "," << c << "\n";
return 0;
}
您在 std::apply
的正确轨道上,但语法不正确;包扩展需要在对 process_arg
的调用之外。另外,您根本不需要变量 success
;你可以直接使用折叠表达式:
bool process1() const
{
return std::apply([](auto &&... v) {
return (process_arg(v) && ...);
}, args);
}
这是一个demo
不确定这是否是您需要的,因为它不会将任何内容存储为成员。但我认为它提供了所需的输出。好吧......也许你可以从中学到一些东西:)
class Handler
{
private:
template <class T>
static bool process_arg(T& val)
{
if constexpr (std::is_same_v<T, int>)
val = 123;
else if constexpr (std::is_same_v<T, std::string>)
val = "string";
else
{
// do something
return false;
}
return true;
}
public:
template<typename arg_t, typename... args_t>
static constexpr bool process(arg_t& arg, args_t&... args)
{
if constexpr (sizeof...(args_t) > 0)
{
bool success = process_arg<arg_t>(arg) && process(args...);
return success;
}
return process_arg<arg_t>(arg);
}
};
int main()
{
int a, b;
std::string c;
Handler::process(a, b, c);
std::cout << a << "," << b << "," << c << "\n";
return 0;
}
我试图在 class 中存储一个引用元组(通过可变参数模板),然后我想“循环”它们并为它们赋值。
下面的函数 process2
按预期工作,但我想让函数 process1
工作相同(利用 class 本身的存储引用)。但是,我无法使 process1
编译。什么是正确的方法?有没有办法让成员 Args&... args;
而不是 std::tuple<Args&...> args
(因为这可能允许参数扩展)?任何建议表示赞赏。
示例代码:
#include <tuple>
#include <string>
#include <iostream>
template<class... Args>
class Handler
{
private:
template <class T>
static bool process_arg(T& val)
{
if constexpr (std::is_same_v<T, int>)
val = 123;
else if constexpr (std::is_same_v<T, std::string>)
val = "string";
else
{
// do something
return false;
}
return true;
}
public:
const std::tuple<Args&...> args;
Handler(Args&... args)
: args(args ...) { }
// bool process1() const
// {
// // Compile Error: operand of fold expression has no unexpanded parameter packs
// const bool success = (process_arg(args) && ...);
// // Compile Error: no matching function for process_arg(int&, int&, std::string&)
// bool success = true;
// std::apply([&success](auto &&... v) { success = success && process_arg(v...); }, args);
// return success;
// }
template<class... Args2>
static bool process2(Args2&... args2)
{
const bool success = (process_arg(args2) && ...);
return success;
}
};
int main()
{
int a, b;
std::string c;
// Handler(a, b, c).process1();
Handler<>::process2(a, b, c);
std::cout << a << "," << b << "," << c << "\n";
return 0;
}
您在 std::apply
的正确轨道上,但语法不正确;包扩展需要在对 process_arg
的调用之外。另外,您根本不需要变量 success
;你可以直接使用折叠表达式:
bool process1() const
{
return std::apply([](auto &&... v) {
return (process_arg(v) && ...);
}, args);
}
这是一个demo
不确定这是否是您需要的,因为它不会将任何内容存储为成员。但我认为它提供了所需的输出。好吧......也许你可以从中学到一些东西:)
class Handler
{
private:
template <class T>
static bool process_arg(T& val)
{
if constexpr (std::is_same_v<T, int>)
val = 123;
else if constexpr (std::is_same_v<T, std::string>)
val = "string";
else
{
// do something
return false;
}
return true;
}
public:
template<typename arg_t, typename... args_t>
static constexpr bool process(arg_t& arg, args_t&... args)
{
if constexpr (sizeof...(args_t) > 0)
{
bool success = process_arg<arg_t>(arg) && process(args...);
return success;
}
return process_arg<arg_t>(arg);
}
};
int main()
{
int a, b;
std::string c;
Handler::process(a, b, c);
std::cout << a << "," << b << "," << c << "\n";
return 0;
}