如果我有一个包装标准容器的模板,似乎我可以合理地轻松委托initializer_list构造函数:
template<typename T>
struct holder {
T t_;
holder() :
t_() {}
holder(std::initializer_list<typename T::value_type> values)
: t_(values) {}
};
Run Code Online (Sandbox Code Playgroud)
因此,这与std :: vector很好地配合.
int main(int argc, char* argv[]) {
holder<std::vector<int>> y{1,2,3};
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
但它很明显不适用于T作为'int',或任何其他没有嵌套value_type typedef的类型.所以,我想使用某种enable_if或类似技巧来使initializer_list构造函数不被发出,除非T都定义了嵌套的value_type typedef,并且可以从std :: initializer_list构造.
我尝试了下面这个,但它仍然不起作用,因为编译器(在我的情况下是clang ++ 3.1),当T为int时仍会跳过无效的T :: value_type:
holder(typename std::enable_if<std::is_constructible<T, std::initializer_list<typename T::value_type>>::value, std::initializer_list<typename T::value_type>>::type values)
: t_(values) {}
Run Code Online (Sandbox Code Playgroud)
关于如何表达概念的任何想法"在T的value_type上给这个模板提供初始化列表构造函数,当且仅当T具有value_type typedef且可从T :: value_type的initializer_list构造时".
假设有一个接受多个字符串的函数:
void fun (const std::initializer_list<std::string>& strings) {
for(auto s : strings)
// do something
}
Run Code Online (Sandbox Code Playgroud)
现在,我有一个可变template函数说foo():
template<typename ...Args>
void foo () {
fun(???);
}
Run Code Online (Sandbox Code Playgroud)
此方法在外部称为:
foo<A, B, C, D>(); // where A, B, C, D are classes
Run Code Online (Sandbox Code Playgroud)
这些作为参数传递的类应该包含一个公共static const成员:
static const std::string value = "...";
Run Code Online (Sandbox Code Playgroud)
以下是我的问题(如何):
foo(),检查是否所有Args包含value使用
static_assertfun()给形成initializer_list; 例如
fun({A::value, B::value, ...});搜索了几个与可变参数模板及其解包相关的线程,但我仍然是这个领域的新手.非常感谢更详细的解释.
我初始化这样的普通类型向量:
vector<float> data = {0.0f, 0.0f};
Run Code Online (Sandbox Code Playgroud)
但是当我使用结构而不是普通类型时
struct Vertex
{
float position[3];
float color[4];
};
vector<Vertex> data = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}};
Run Code Online (Sandbox Code Playgroud)
我收到错误could not convert '{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}' from '<brace-enclosed initializer list>' to 'std::vector<Vertex>'.这有什么问题?
尝试传递可变数量的初始化列表时,我不明白错误消息:
template<typename... Values>
void foo(Values...)
{
}
int main()
{
foo(1, 2, 3, "hello", 'a'); // OK
foo({1}, {2, 3}); // ERROR
}
Run Code Online (Sandbox Code Playgroud)
错误消息抱怨参数太多:
prog.cpp: In function ‘int main()’:
prog.cpp:9:20: error: too many arguments to function
‘void foo(Values ...) [with Values = {}]’
foo({1}, {2, 3});
^
prog.cpp:2:6: note: declared here
void foo(Values...)
^
Run Code Online (Sandbox Code Playgroud)
但是,我是否应该无法传递尽可能多的参数?[ 意见链接 ]
给定一个A带有两个构造函数的类,分别取initializer_list<int>和initializer_list<initializer_list<int>>
A v{5,6};
Run Code Online (Sandbox Code Playgroud)
叫前者,和
A v{{5,6}};
Run Code Online (Sandbox Code Playgroud)
按预期调用后者.(clang3.3,显然gcc表现不同,请看答案.标准需要什么?)
但是如果我删除第二个构造函数,那么A v{{5,6}};仍然编译并使用第一个构造函数.我没想到这一点.我认为这A v{5,6}将是访问构造函数的唯一方法initializer_list<int>.
(我发现这一点的同时与玩弄std::vector和这个问题,我问在Reddit上,但我创建了自己的A级,以确保它不只是一个对接口的怪癖std::vector.)
我有以下课程:
class Foo
{
public:
Foo(double a, double b, double c, double d, double e)
// This does not work:
// : m_bar(a, b, c, d, e)
{
m_bar << a, b, c, d, e;
}
private:
// How can I make this const?
Eigen::Matrix<double, 5, 1, Eigen::DontAlign> m_bar;
};
Run Code Online (Sandbox Code Playgroud)
我如何制作m_bar const并将其初始化为a到f作为构造函数中的值?C++ 11也没问题,但初始化程序列表似乎不受eigen支持...
在C++ 11中,可以使用初始化列表来初始化函数中的参数.它的目的是什么?使用const向量不能做同样的事情吗?以下两个程序有什么区别?
使用初始化列表:
#include <iostream>
using namespace std;
int sumL(initializer_list<int> l){
int sum = 0;
for (const auto i: l){
sum += i;
}
return sum;
}
int main(){
cout << sumL({1, 2, 3}) << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用const向量:
#include <iostream>
#include <vector>
using namespace std;
int sumV(const vector<int> l){
int sum = 0;
for (const auto i: l){
sum += i;
}
return sum;
}
int main(){
cout << sumV({1, 2, 3}) << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我正在玩一些无用的代码来理解成员引用的初始化,并碰到了这个:
struct A {};
struct B
{
B() : a()
{
}
const A& a;
};
Run Code Online (Sandbox Code Playgroud)
使用gcc 4.9.2编译时,上面的代码给出以下错误:
In constructor 'B::B()':
error: value-initialization of reference type 'const A&'
B() : a()
Run Code Online (Sandbox Code Playgroud)
我明白了
但是如果我在B的构造函数的初始化列表中使用统一初始化,就像这样:
struct A {};
struct B
{
B() : a{}
{
}
const A& a;
};
Run Code Online (Sandbox Code Playgroud)
它汇编很好.
所以问题是,为什么在这里使用统一初始化会改变编译结果?
我也尝试使用Microsoft Visual C++ 2013.它不编译任何版本的代码,并使用相同的错误消息:
Error 3 error C2440: 'initializing' : cannot convert from 'int' to 'const A &
Run Code Online (Sandbox Code Playgroud)
你可以在这里快速玩它:
max({"a", "b", "z", "x"}); returns "x"
Run Code Online (Sandbox Code Playgroud)
两者都有
max<std::string>({"a", "b", "z", "x"});
Run Code Online (Sandbox Code Playgroud)
和
max({'a', 'b', 'z', 'x'});
Run Code Online (Sandbox Code Playgroud)
按原样返回"z".为什么?
考虑以下代码:
#include <vector>
#define BROKEN
class Var {
public:
#ifdef BROKEN
template <typename T>
Var(T x) : value(x) {}
#else
Var(int x) : value(x) {}
#endif
int value;
};
class Class {
public:
Class(std::vector<Var> arg) : v{arg} {}
std::vector<Var> v;
};
Run Code Online (Sandbox Code Playgroud)
不管是否BROKEN定义,Clang ++(7.0.1)都会编译此错误,而如果BROKEN已定义,则g ++(8.2.1)会引发错误:
main.cpp:9:20: error: cannot convert ‘std::vector<Var>’ to ‘int’ in initialization
Var(T x) : value(x) {}
^
Run Code Online (Sandbox Code Playgroud)
据我所知,std::vector(std::vector&&)在两种情况下,这里使用的统一初始化都应选择构造函数。但是,显然,g++它将{arg}视为初始化列表,并尝试初始化应用于向量的vwith 的第一个元素Var,这将不起作用。
如果BROKEN未定义,则g ++显然足够聪明,可以意识到initializer_list重载将无法正常工作。
哪个是正确的行为,或者标准都允许? …