我需要一个带有可变数量参数的模板函数。目前我的问题通过使用几个模板函数来解决。但是现在我需要在我的类函数和其他原因中创建一个wrap方法来将这个代码打包到一个函数中。
static void sendData(SSL *ssl, Command com)
{
std::string comStr(COM_SIZE, ' ');
memcpy(&comStr[0], &com, COM_SIZE);
sslWrite(ssl, comStr);
}
template<class T>
void sendData(SSL *ssl, Command com, const T &t)
{
std::string serialArg;
OByteStream obs(serialArg);
obs << t;
obs.flush();
const int serialArgSize = serialArg.size();
std::string comAndSerialData(COM_SIZE + serialArgSize, ' ');
memcpy(&comAndSerialData[0], &com, COM_SIZE);
memcpy(&comAndSerialData[COM_SIZE], &serialArg[0], serialArgSize);
sslWrite(ssl, comAndSerialData);
}
template<class T1, class T2>
void sendData(SSL *ssl, Command com, const T1 &t1, const T2 &t2)
{
std::string serialArgs;
OByteStream obs(serialArgs);
obs << t1 << t2;
obs.flush();
const int serialArgsSize = serialArgs.size();
std::string comAndSerialData(COM_SIZE + serialArgsSize, ' ');
memcpy(&comAndSerialData[0], &com, COM_SIZE);
memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize);
sslWrite(ssl, comAndSerialData);
}
template<class T1, class T2, class T3>
void sendData(SSL *ssl, Command com, const T1 &t1, const T2 &t2, const T3 &t3)
{
std::string serialArgs;
OByteStream obs(serialArgs);
obs << t1 << t2 << t3;
obs.flush();
const int serialArgsSize = serialArgs.size();
std::string comAndSerialData(COM_SIZE + serialArgsSize, ' ');
memcpy(&comAndSerialData[0], &com, COM_SIZE);
memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize);
sslWrite(ssl, comAndSerialData);
}
//...
我如何在一个函数中写这个?
这是我尝试使用可变参数模板
void flush(OByteStream &obs)
{
obs.flush();
}
template<typename T, typename... Targs>
void flush(OByteStream &obs, T value, Targs... Fargs)
{
obs << value;
flush(obs, Fargs);
}
template<typename... Targs>
void sendData(SSL *ssl, Command com, Targs... Fargs)
{
std::string serialArgs;
OByteStream obs(serialArgs);
flush(obs, Fargs);
const int serialArgsSize = serialArgs.size();
std::string comAndSerialData(COM_SIZE + serialArgsSize, ' ');
memcpy(&comAndSerialData[0], &com, COM_SIZE);
memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize);
sslWrite(ssl, comAndSerialData);
}
flush(obs, Fargs);
- 错误C3520:'Fargs':参数包必须在此上下文中展开
答案 0 :(得分:6)
template<class...Ts>
void sendData(SSL *ssl, Command com, const Ts&... ts)
...
将<<
行替换为:
for_each_arg([&](auto&&t){obs << t;},ts...);
写for_each_arg
:
template<class F,class...Ts>
void for_each_arg(F&&f, Ts&&... ts){
using discard=int[];
(void)discard{ 0, ((
f(std::forward<Ts>(ts))
),void(),0)...}
}
这是神秘而有效的。
这在C ++ 11上变得更难,因为你没有auto&&
lambdas。您可以使用模板operator()
编写手动结构。
这自然不会取代零arg情况,并且考虑到你的代码有多短,我不会把自己扭曲成pretzils来处理它。
如何使用模板运算符()替换C ++ 14自动lambda来编写C ++ 11函数对象?
假设您有一个C ++ 14 lambda,如下所示:
auto f = [&](auto&& x) { /* some code */ };
将其转换为带有模板operator()
的C ++ 11函数对象,首先标识要捕获的每个实际内容,然后手动捕获它们。假设/* code */
使用名称bob
alice
并隐式使用this
。然后重写这样的行:
auto f = [&bob, &alice, this](auto&& x) { /* some code */ };
我们列出我们捕获的所有内容。
接下来,取/* some code */
并使用this
明确。如果我们使用m_x
,请将其替换为this->m_x
。
下一步是确定bob
alice
和this
的类型。假设它们是Bob
Alice
和MyClass
。创建一个类似于以下的类:
struct function_object_f {
Bob const& bob;
Alice const& alice;
MyClass* self;
};
按顺序捕获变量。现在添加template operator()
:
struct function_object_f {
Bob const& bob;
Alice const& alice;
MyClass* self;
template<class X>
void operator()(X&& x)const {
/* some code */
}
};
现在,用this
替换/* some code */
中self
的每一个明确提及。
在你的函数之前把这个类放在使用lambda的地方。
重写原始行:
auto f = function_object_f{bob, alice, this};
我们完成了。 (请注意,捕获的顺序在这里很重要:它必须与function_object_f
成员变量声明匹配)。 f
几乎与lambda相同,但其类型有一个名称。
(对于没有捕获的lambdas,它缺少隐式转换为函数的指针,但这是另一天的样板文件。)
答案 1 :(得分:1)
inline void flush(OByteStream &obs)
{
obs.flush();
}
template<typename T, typename... Targs>
void flush(OByteStream &obs, T &value, Targs&... Fargs)
{
obs << value;
flush(obs, Fargs...);
}
template<typename... Targs>
void sendData(SSL *ssl, Command com, Targs&... Fargs)
{
std::string serialArgs;
OByteStream obs(serialArgs);
flush(obs, Fargs...);
const int serialArgsSize = serialArgs.size();
std::string comAndSerialData(COM_SIZE + serialArgsSize, ' ');
memcpy(&comAndSerialData[0], &com, COM_SIZE);
memcpy(&comAndSerialData[COM_SIZE], &serialArgs[0], serialArgsSize);
sslWrite(ssl, comAndSerialData);
}
答案 2 :(得分:0)
您可以用
替换两个刷新功能pow_factory = -> (exp) {-> (base) {pow.(base, exp: exp)}}
cube = pow_factory.(3)
这种技术避免了递归。当然,您可以使用您需要的任何函数调用替换template<typename... Targs>
void flush(OByteStream &obs, Targs... Fargs)
{
using swallow = int[sizeof...(Targs)];
(void) swallow{(obs << Fargs, 0)...};
}
:
obs << Fargs