C++11 中的混合列表初始化
Mixed list initialization in C++11
参考c++11 list initialization,我可以用一个元素和另一个列表初始化一个列表吗?
假设我有以下代码:
#include <vector>
class Foo
{
public:
Foo(int value){m_v=value;}
private:
int m_v = 0;
};
int main()
{
std::vector<Foo> v1, v2, v3;
v1 = {Foo(1)}; //ok
v2 = {Foo(2), Foo(3)}; //ok
v3 = {Foo(3), v2}; //error: no match for ‘operator=’ (operand types are ‘std::vector’ and ‘’)
}
有没有一种方法可以使用列表初始化在一行代码中创建一个向量,该向量由另一个向量的元素加上一个新元素(在上面的示例中是前置项)组成。
std::vector<Foo>
表示 std::vector
个 Foo
个实例。这意味着它不能任意存储其他 std::vector
个实例,这就是您在编写
时询问编译器的内容
v3 = {Foo(3), v2};
std::initializer_list<T>
是 T
个实例的同类集合。 std::vector<Foo>
的列表构造函数采用 std::initializer_list<Foo>
。如果不手动解压缩花括号内的 v2
元素,就无法实现您想要的效果。
Is there a way to create in one line of code, using list initialization, a vector made of the element of another vector plus a new element (a prepend, in the example above).
使用列表初始化,没有。但是,您可以编写自己的函数来实现相同的目的。
我们可以创建一些模板基础结构,以允许通过对象和其他向量的可选串联来创建向量。
这是第一次剪辑:
#include <utility>
#include <vector>
namespace extended
{
template<class T>
struct appender
{
template<class V, class A, class Arg>
void operator()(std::vector<V, A>& vec, Arg&& arg) const
{
vec.push_back(std::forward<Arg>(arg));
}
};
template<class V2, class A2>
struct appender<std::vector<V2, A2>>
{
template<class V, class A, class X>
void operator()(std::vector<V, A>& vec, X&& arg) const
{
vec.insert(end(vec), begin(std::forward<X>(arg)), end(std::forward<X>(arg)));
}
};
template<class V, class A, class T>
auto append(std::vector<V, A>& target, T&& x) -> decltype(auto)
{
auto op = appender<std::decay_t<T>>();
op(target, std::forward<T>(x));
return target;
}
}
template<class T, class...Args>
auto make_vector(Args&&...args)
{
using extended::append;
std::vector<T> result;
using expand = int[];
expand {0,
(append(result, std::forward<Args>(args)), 0)...
};
return result;
}
class Foo
{
public:
Foo(int value){m_v=value;}
private:
int m_v = 0;
};
int main()
{
auto v1 = make_vector<Foo>(Foo(1)); //ok
auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok
auto v3 = make_vector<Foo>(Foo(3), v2); //ok
}
当然,通过寻找通用接口,我们可以开始稍微突破界限:
#include <utility>
#include <iterator>
#include <vector>
#include <list>
#include <set>
namespace extended
{
// The general case of an appender.
// simply calls emplace_back
template<class T, class Diff = void>
struct appender
{
template<class V, class A, class Arg>
void operator()(std::vector<V, A>& vec, Arg&& arg) const
{
vec.emplace_back(std::forward<Arg>(arg));
}
};
// specific specialisation for an appender where the
// source object supports begin() and end() (i.e. a container)
//
template<class T>
struct appender
<
T,
decltype(
std::begin(std::declval<T>()),
std::end(std::declval<T>()),
void()
)
>
{
template<class V, class A, class X>
void operator()(std::vector<V, A>& vec, X&& arg) const
{
vec.insert(std::end(vec), std::begin(std::forward<X>(arg)), std::end(std::forward<X>(arg)));
}
};
template<class V, class A, class T>
auto append(std::vector<V, A>& target, T&& x) -> decltype(auto)
{
auto op = appender<std::decay_t<T>>();
op(target, std::forward<T>(x));
return target;
}
}
template<class T, class...Args>
auto make_vector(Args&&...args)
{
using extended::append;
std::vector<T> result;
using expand = int[];
expand {0,
(append(result, std::forward<Args>(args)), 0)...
};
return result;
}
class Foo
{
public:
Foo(int value){m_v=value;}
bool operator<(const Foo& r) const { return m_v < r.m_v; }
private:
int m_v = 0;
};
int main()
{
auto v1 = make_vector<Foo>(Foo(1)); //ok
auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok
auto v3 = make_vector<Foo>(Foo(3), v2); //ok
auto v4 = make_vector<Foo>(Foo(1),
std::list<Foo> { Foo(2), Foo(3) },
make_vector<Foo>(4, make_vector<Foo>(8, 9, 10)),
std::set<Foo> {Foo(6), Foo(7) }); // bizzare but ok
}
参考c++11 list initialization,我可以用一个元素和另一个列表初始化一个列表吗?
假设我有以下代码:
#include <vector>
class Foo
{
public:
Foo(int value){m_v=value;}
private:
int m_v = 0;
};
int main()
{
std::vector<Foo> v1, v2, v3;
v1 = {Foo(1)}; //ok
v2 = {Foo(2), Foo(3)}; //ok
v3 = {Foo(3), v2}; //error: no match for ‘operator=’ (operand types are ‘std::vector’ and ‘’)
}
有没有一种方法可以使用列表初始化在一行代码中创建一个向量,该向量由另一个向量的元素加上一个新元素(在上面的示例中是前置项)组成。
std::vector<Foo>
表示 std::vector
个 Foo
个实例。这意味着它不能任意存储其他 std::vector
个实例,这就是您在编写
v3 = {Foo(3), v2};
std::initializer_list<T>
是 T
个实例的同类集合。 std::vector<Foo>
的列表构造函数采用 std::initializer_list<Foo>
。如果不手动解压缩花括号内的 v2
元素,就无法实现您想要的效果。
Is there a way to create in one line of code, using list initialization, a vector made of the element of another vector plus a new element (a prepend, in the example above).
使用列表初始化,没有。但是,您可以编写自己的函数来实现相同的目的。
我们可以创建一些模板基础结构,以允许通过对象和其他向量的可选串联来创建向量。
这是第一次剪辑:
#include <utility>
#include <vector>
namespace extended
{
template<class T>
struct appender
{
template<class V, class A, class Arg>
void operator()(std::vector<V, A>& vec, Arg&& arg) const
{
vec.push_back(std::forward<Arg>(arg));
}
};
template<class V2, class A2>
struct appender<std::vector<V2, A2>>
{
template<class V, class A, class X>
void operator()(std::vector<V, A>& vec, X&& arg) const
{
vec.insert(end(vec), begin(std::forward<X>(arg)), end(std::forward<X>(arg)));
}
};
template<class V, class A, class T>
auto append(std::vector<V, A>& target, T&& x) -> decltype(auto)
{
auto op = appender<std::decay_t<T>>();
op(target, std::forward<T>(x));
return target;
}
}
template<class T, class...Args>
auto make_vector(Args&&...args)
{
using extended::append;
std::vector<T> result;
using expand = int[];
expand {0,
(append(result, std::forward<Args>(args)), 0)...
};
return result;
}
class Foo
{
public:
Foo(int value){m_v=value;}
private:
int m_v = 0;
};
int main()
{
auto v1 = make_vector<Foo>(Foo(1)); //ok
auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok
auto v3 = make_vector<Foo>(Foo(3), v2); //ok
}
当然,通过寻找通用接口,我们可以开始稍微突破界限:
#include <utility>
#include <iterator>
#include <vector>
#include <list>
#include <set>
namespace extended
{
// The general case of an appender.
// simply calls emplace_back
template<class T, class Diff = void>
struct appender
{
template<class V, class A, class Arg>
void operator()(std::vector<V, A>& vec, Arg&& arg) const
{
vec.emplace_back(std::forward<Arg>(arg));
}
};
// specific specialisation for an appender where the
// source object supports begin() and end() (i.e. a container)
//
template<class T>
struct appender
<
T,
decltype(
std::begin(std::declval<T>()),
std::end(std::declval<T>()),
void()
)
>
{
template<class V, class A, class X>
void operator()(std::vector<V, A>& vec, X&& arg) const
{
vec.insert(std::end(vec), std::begin(std::forward<X>(arg)), std::end(std::forward<X>(arg)));
}
};
template<class V, class A, class T>
auto append(std::vector<V, A>& target, T&& x) -> decltype(auto)
{
auto op = appender<std::decay_t<T>>();
op(target, std::forward<T>(x));
return target;
}
}
template<class T, class...Args>
auto make_vector(Args&&...args)
{
using extended::append;
std::vector<T> result;
using expand = int[];
expand {0,
(append(result, std::forward<Args>(args)), 0)...
};
return result;
}
class Foo
{
public:
Foo(int value){m_v=value;}
bool operator<(const Foo& r) const { return m_v < r.m_v; }
private:
int m_v = 0;
};
int main()
{
auto v1 = make_vector<Foo>(Foo(1)); //ok
auto v2 = make_vector<Foo>(Foo(2), Foo(3)); //ok
auto v3 = make_vector<Foo>(Foo(3), v2); //ok
auto v4 = make_vector<Foo>(Foo(1),
std::list<Foo> { Foo(2), Foo(3) },
make_vector<Foo>(4, make_vector<Foo>(8, 9, 10)),
std::set<Foo> {Foo(6), Foo(7) }); // bizzare but ok
}