我正在尝试学习可变参数模板和函数.我无法理解为什么这段代码不能编译:
template<typename T>
static void bar(T t) {}
template<typename... Args>
static void foo2(Args... args)
{
(bar(args)...);
}
int main()
{
foo2(1, 2, 3, "3");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译它失败时出现错误:
错误C3520:'args':必须在此上下文中扩展参数包
(在功能上foo2).
在Boost邮件列表中,@ LouisDionne最近发布了以下创建类似元组的实体的巧妙技巧:
#include <iostream>
auto list = [](auto ...xs) {
return [=](auto access) { return access(xs...); };
};
auto length = [](auto xs) {
return xs([](auto ...z) { return sizeof...(z); });
};
int main()
{
std::cout << length(list(1, '2', "3")); // 3
}
Run Code Online (Sandbox Code Playgroud)
实例.
聪明之处在于listlambda采用可变参数列表作为输入,并返回lambda作为输出,将另一个lambda作用于其输入.类似地,lengthlambda是一个类似列表的实体,它将sizeof...向列表的原始输入参数提供可变参数运算符.在sizeof...操作上缠绕有拉姆达的内部,使得它可以被传递给list.
问题:这个元组创作成语是否有名称?也许来自函数式编程语言,其中更常用的是高阶函数.
我正在尝试找到一个迭代包变量模板参数列表的方法.现在和所有迭代一样,您需要某种方法来了解打包列表中有多少参数,更重要的是如何从打包参数列表中单独获取数据.
一般的想法是迭代列表,将int类型的所有数据存储到向量中,将char*类型的所有数据存储到向量中,并将float类型的所有数据存储到向量中.在这个过程中,还需要一个单独的向量来存储参数进入顺序的各个字符.例如,当你push_back(a_float)时,你也在做一个push_back('f'),它只是存储一个单独的char来了解数据的顺序.我也可以在这里使用std :: string,只需使用+ =.该矢量仅用作示例.
现在,事物的设计方式是功能本身是使用宏构建的,尽管存在恶意,但它是必需的,因为这是一个实验.因此,使用递归调用几乎是不可能的,因为将包含所有这些的实际实现将在编译时扩展; 你不能招募一个宏.
尽管有各种可能的尝试,我仍然坚持要弄清楚如何实际做到这一点.所以相反,我使用了一个更复杂的方法,包括构造一个类型,并将该类型传递到varadic模板,在一个向量中扩展它,然后简单地迭代它.但是我不想像以下那样调用函数:
foo(arg(1), arg(2.0f), arg("three");
Run Code Online (Sandbox Code Playgroud)
所以真正的问题是如果没有这样的话我该怎么办?为了让你们更好地理解代码实际在做什么,我已经粘贴了我目前正在使用的乐观方法.
struct any {
void do_i(int e) { INT = e; }
void do_f(float e) { FLOAT = e; }
void do_s(char* e) { STRING = e; }
int INT;
float FLOAT;
char *STRING;
};
template<typename T> struct get { T operator()(const any& t) { return T(); } };
template<> struct get<int> { int operator()(const any& t) { return t.INT; } };
template<> struct get<float> { float operator()(const any& …Run Code Online (Sandbox Code Playgroud) 函数one()接受一个参数包.函数二()接受两个.每个包都被约束为包裹在类型A和B中.为什么不可能实例化两个()?
template <typename T>
struct A {};
template <typename T>
struct B {};
template <typename... Ts>
void one(A<Ts> ...as) {
}
template <typename... Ts, typename... Us>
void two(A<Ts> ...as, B<Us> ...bs) {
}
int main() {
auto a = A<int>();
auto b = B<int>();
// Just fine
one();
one(a);
one(a, a);
// All errors
two();
two(a);
two(a, b);
}
Run Code Online (Sandbox Code Playgroud)
试过gcc和clang.
sam@wish:~/x/cpp$ gcc -std=c++0x variadic_templates.cpp
variadic_templates.cpp: In function ‘int main()’:
variadic_templates.cpp:23:7: …Run Code Online (Sandbox Code Playgroud) 从本质上讲,我希望自动像功能的建立std::make_pair,std::bind1st并且std::mem_fun,使不必编写为每个模板类类型不同的功能,你可以编写处理所有情况下,一旦一个可变参数模板模板功能.这个函数的用法如下:
make<std::pair>(1, 2); // equivalent to std::make_pair(1, 2)
make<std::binder2nd>(&foo, 3); // equivalent to std::bind2nd(&foo, 3);
Run Code Online (Sandbox Code Playgroud)
有可能写这个功能make吗?我试过这个,但它在GCC 4.5或4.6中不起作用:
template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
return TemplateClass<Args...>(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
如果我试着打电话(例如)make<std::pair>(1, 2)我就得到
error: no matching function for call to 'make(int, int)'
Run Code Online (Sandbox Code Playgroud)
我在这里的语法错了吗?
或者这是对的,海湾合作委员会是错的吗?
或者这在C++ 0x中根本不可能?
[编辑]
建议N2555似乎表明这是允许的,海湾合作委员会声称已在GCC4.4中实施.
我一直在学习可变参数模板,在这篇优秀博客文章的帮助下,我设法编写了一个函数模板even_number_of_args,它返回它接收的参数数量是否可被2整除.
#include <iostream>
bool even_number_of_args() {
return true;
}
template <typename T>
bool even_number_of_args(T _) {
return false;
}
template<typename T, typename U, typename... Vs>
bool even_number_of_args(T _, U __, Vs... vs) {
return even_number_of_args(vs...);
}
int main() {
std::cout << even_number_of_args() << std::endl; // true
std::cout << even_number_of_args(1) << std::endl; // false
std::cout << even_number_of_args(1, "two") << std::endl; // true
std::cout << even_number_of_args(1, "two", 3.0) << std::endl; // false
std::cout << even_number_of_args(1, "two", 3.0, '4') …Run Code Online (Sandbox Code Playgroud) 考虑以下类模板"X"及其部分特化.
template <class ...Types>
struct X {}; // #1
template <class T1>
struct X<T1> {}; // #2
template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3
X<int> x; // #2 or #3 ?
Run Code Online (Sandbox Code Playgroud)
我怀疑X <int>是不明确的.这是因为:
很明显,#2和#3都比#1更专业,现在比较#2和#3.根据14.5.5.2,让我们考虑以下哪个#2'和#3'更专业.
template <class T1>
void f(X<T1>); // #2'
template <class T1, class ...Types>
void f(X<T1, Types...>); // #3'
Run Code Online (Sandbox Code Playgroud)
根据14.8.2.4,第一步是模板参数推导,使用#2'作为参数模板,#3'作为参数模板.给定唯一的参数类型是X <A1>,推导出的T1是A1,而Types是空的.
A = X<A1>, P = X<T1, Types...> => T1 = A1, Types = {}
Run Code Online (Sandbox Code Playgroud)
第二步是使用#3'作为参数模板,使用#2'作为参数模板.鉴于唯一的参数类型是X <A1,Args ...>,根据14.8.2.5/9(注意该段最近由N3281修订),Args被简单地忽略,推断的T1是A1并且参数推断成功.
A = X<A1, Args...>, P = …Run Code Online (Sandbox Code Playgroud) c++ templates template-specialization variadic-templates c++11
我想要做
template<typename... ArgTypes> void print(ArgTypes... Args)
{
print(Args)...;
}
Run Code Online (Sandbox Code Playgroud)
并且它相当于这个相当庞大的递归链:
template<typename T, typename... ArgTypes> void print(const T& t, ArgTypes... Args)
{
print(t);
print(Args...);
}
Run Code Online (Sandbox Code Playgroud)
然后是我想要打印的每种类型的显式单参数专精.
递归实现的"问题"是生成了大量冗余代码,因为每个递归步骤都会产生一个新的N-1参数函数,而我想要的代码只会为单个N-arg print函数生成代码,并且具有最多的N专业print功能.
如果我定义了一个struct模板Bar,它接受一个模板参数:
template <template <int,bool,char> class>
struct Bar {};
Run Code Online (Sandbox Code Playgroud)
我可以使用以下struct模板对其进行实例化Zod:
template <int,bool,char> struct Zod {};
Bar<Zod> a;
Run Code Online (Sandbox Code Playgroud)
我也可以使用嵌套struct模板来实例化它,例如JKL:
struct GHI {
template <int,bool,char>
struct JKL {};
};
Bar <GHI::JKL> b;
Run Code Online (Sandbox Code Playgroud)
为什么我不能Bar使用嵌套的可变参数struct模板实例化,例如DEF?:
template <typename ...Ts>
struct ABC {
template <Ts ...>
struct DEF {};
};
Bar<ABC<int,bool,char>::DEF> c;
Run Code Online (Sandbox Code Playgroud)
G ++ 4.9.2抱怨类型/值不匹配; 而Clang 3.4.2的错误报告模板模板参数具有与其对应的模板模板参数不同的模板参数.
我们可以将可变参数模板参数限制为某种类型吗?即,实现类似的东西(当然不是真正的C++):
struct X {};
auto foo(X... args)
Run Code Online (Sandbox Code Playgroud)
在这里,我的目的是拥有一个接受可变数量X参数的函数.
我们最接近的是:
template <class... Args>
auto foo(Args... args)
Run Code Online (Sandbox Code Playgroud)
但是这接受任何类型的参数.