所以我有一些类型X:
typedef ... X;
Run Code Online (Sandbox Code Playgroud)
和模板功能f:
class <typename T>
void f(X& x_out, const T& arg_in);
Run Code Online (Sandbox Code Playgroud)
然后是一个功能g:
void g(const X* x_array, size_t x_array_size);
Run Code Online (Sandbox Code Playgroud)
我需要编写一个variadic模板函数h来执行此操作:
template<typename... Args>
void h(Args... args)
{
constexpr size_t nargs = sizeof...(args); // get number of args
X x_array[nargs]; // create X array of that size
for (int i = 0; i < nargs; i++) // foreach arg
f(x_array[i], args[i]); // call f (doesn't work)
g(x_array, nargs); // call g with …Run Code Online (Sandbox Code Playgroud) 如何将参数包拆分为两个相等的部分?
例如,我想做这样的事情:
template<typename T> T sum(const T& t)
{ return t; }
template<typename T> T sum(const T& t1, const T& t2)
{ return t1 + t2; }
template<typename ...T> T sum(T&& ...t)
{ sum(first_half(t)...) + sum(second_half(t)...); }
Run Code Online (Sandbox Code Playgroud) 以下程序编译成功。
template<typename T>
T sum(T x) {
return x;
}
template<typename T, typename... Args>
T sum(T x, Args... args) {
return x + sum(args...);
}
int main() {
sum(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
但是,当我切换模板函数的编写顺序时,它不再编译:
template<typename T, typename... Args>
T sum(T x, Args... args) {
return x + sum(args...);
}
template<typename T>
T sum(T x) {
return x;
}
int main() {
sum(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
我得到的编译器错误是:
错误 C2780:“T sum(T,Args...)”:需要 2 个参数 - 提供 0 个,消息:请参阅“sum”的声明
为什么会出现这种情况?这两个函数在 main() …
考虑以下代码:
#include <iostream>
using namespace std;
class hello{
public:
void f(){
cout<<"f"<<endl;
}
virtual void ff(){
cout<<"ff"<<endl;
}
};
#define call_mem_fn(object, ptr) ((object).*(ptr))
template<R (C::*ptr_to_mem)(Args...)> void proxycall(C& obj){
cout<<"hello"<<endl;
call_mem_fn(obj, ptr_to_mem)();
}
int main(){
hello obj;
proxycall<&hello::f>(obj);
}
Run Code Online (Sandbox Code Playgroud)
当然,这不会在第16行编译,因为编译器不知道是什么R,C并且Args,是.但还有另一个问题:如果有人试图在之前定义这些模板参数ptr_to_mem,他会遇到这种糟糕的情况:
template<typename R, typename C, typename... Args, R (C::*ptr_to_mem)(Args...)>
// ^variadic template, but not as last parameter!
void proxycall(C& obj){
cout<<"hello"<<endl;
call_mem_fn(obj, ptr_to_mem)();
}
int main(){
hello obj;
proxycall<void, hello, &hello::f>(obj);
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,g ++没有抱怨 …
在多次调用时,为什么C++ lambda比普通函数慢?和C++ 0x Lambda开销 但我认为我的例子与前者的讨论有点不同,并且与后者的结果相矛盾.
在我的代码中搜索瓶颈时,我发现了一个recusive模板函数,它处理具有给定处理器函数的可变参数列表,比如将值复制到缓冲区中.
template <typename T>
void ProcessArguments(std::function<void(const T &)> process)
{}
template <typename T, typename HEAD, typename ... TAIL>
void ProcessArguments(std::function<void(const T &)> process, const HEAD &head, const TAIL &... tail)
{
process(head);
ProcessArguments(process, tail...);
}
Run Code Online (Sandbox Code Playgroud)
我将使用此代码的程序的运行时与lambda函数以及使用移动指针将参数复制到全局缓冲区的全局函数进行了比较:
int buffer[10];
int main(int argc, char **argv)
{
int *p = buffer;
for (unsigned long int i = 0; i < 10E6; ++i)
{
p = buffer;
ProcessArguments<int>([&p](const int &v) { *p++ = v; …Run Code Online (Sandbox Code Playgroud) 这是关于gcc 4.9.2和clang 3.5.2存在尖锐分歧的一点.该程序:
template<typename ...Ts>
int foo(int i = 0, Ts &&... args)
{
return i + sizeof...(Ts);
}
int main()
{
return foo();
}
Run Code Online (Sandbox Code Playgroud)
编译没有gcc(-std=c++11 -Wall -pedantic)的评论.Clang说:
error: missing default argument on parameter 'args'
Run Code Online (Sandbox Code Playgroud)
随着foo修订为:
template<typename ...Ts>
int foo(int i = 0, Ts &&... args = 0)
{
return i + sizeof...(Ts);
}
Run Code Online (Sandbox Code Playgroud)
clang没有抱怨,但gcc说:
error: parameter pack ‘args’ cannot have a default argument
Run Code Online (Sandbox Code Playgroud)
哪个编译器是对的?
从C++ 11开始,我们可以创建可以接受任何参数序列的模板函数:
template <typename... Ts>
void func(Ts &&... ts) {
step_one(std::forward<Ts>(ts)...);
step_two(std::forward<Ts>(ts)...);
}
Run Code Online (Sandbox Code Playgroud)
但是,假设在每个参数具有相同类型的情况下调用我的函数真的是有意义的 - 任何数量的参数都可以.
这样做的最佳方法是什么,即在这种情况下是否有一种很好的方法来约束模板以生成一个很好的错误消息,或者理想情况下,func当参数不匹配时,可以避免参与重载解析?
如果它有帮助我可以使它真正具体:
假设我有一些结构:
struct my_struct {
int foo;
double bar;
std::string baz;
};
Run Code Online (Sandbox Code Playgroud)
现在,我希望能够执行以下操作:打印结构的成员以进行调试,序列化和反序列化结构,按顺序访问结构的成员等.我有一些代码可以帮助解决这个问题:
template <typename V>
void apply_visitor(V && v, my_struct & s) {
std::forward<V>(v)("foo", s.foo);
std::forward<V>(v)("bar", s.bar);
std::forward<V>(v)("baz", s.baz);
}
template <typename V>
void apply_visitor(V && v, const my_struct & s) {
std::forward<V>(v)("foo", s.foo);
std::forward<V>(v)("bar", s.bar);
std::forward<V>(v)("baz", s.baz);
}
template <typename V>
void apply_visitor(V && v, my_struct && s) { …Run Code Online (Sandbox Code Playgroud) 我不明白为什么这不起作用.知道模板和可变参数表达式折叠的人能解释发生了什么并提供一个有效的解决方案吗?
#include <iostream>
#include <string>
template <typename... Args>
void print(Args... args)
{
std::string sep = " ";
std::string end = "\n";
(std::cout << ... << sep << args) << end;
}
int main()
{
print(1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)
它应该打印出每个args,其间有一个空格,最后一个换行符.如果你删除了它,sep <<但是在打印时每个参数之间没有空格.
在尝试使用C++ 17折叠表达式时,我试图实现max sizeof,其中结果是最多sizeof的类型.我有一个使用变量和lambda的丑陋折叠版本,但我无法想到使用折叠表达式并std::max()获得相同结果的方法.
这是我的折叠版本:
template<typename... T>
constexpr size_t max_sizeof(){
size_t max=0;
auto update_max = [&max](const size_t& size) {if (max<size) max=size; };
(update_max(sizeof (T)), ...);
return max;
}
static_assert(max_sizeof<int, char, double, short>() == 8);
static_assert(max_sizeof<char, float>() == sizeof(float));
static_assert(max_sizeof<int, char>() == 4);
Run Code Online (Sandbox Code Playgroud)
我想用折叠表达式编写等效函数std::max().例如,对于3个元素,它应该扩展为
return std::max(sizeof (A), std::max(sizeof(B), sizeof (C)));
Run Code Online (Sandbox Code Playgroud)
有可能吗?
如何将可变参数模板参数分成两半?就像是:
template <int d> struct a {
std::array <int, d> p, q;
template <typename ... T> a (T ... t) : p ({half of t...}), q ({other half of t...}) {}
};
Run Code Online (Sandbox Code Playgroud)