[英]C++ passing parameter pack to class
I'd like to have a class that gets in it's Ctor unlimited parameters of the same type, and stores them into a vector.我想要一个类,它可以获取相同类型的 Ctor 无限参数,并将它们存储到一个向量中。 It should look like that:它应该是这样的:
class A(int a, int b, **N time parameter of type T**)
: data(**vector will get N times type T**)
{
}
protected:
vector<T> data;
How should I implement it?我应该如何实施它? Solution could be in c++11/14 I got a few errors such as "parameter packs not expanded with '…' ", etc..解决方案可能是在 c++11/14 中,我收到了一些错误,例如“参数包未使用 '...' 扩展”等。
This code sample might be useful:此代码示例可能有用:
#include <vector>
#include <utility>
template<typename T>
class MyClass {
public:
template<typename ...Args>
MyClass(int a, int b, Args&& ...args) :data{ std::forward<Args>(args)... } {}
private:
std::vector<T> data;
};
int main() {
MyClass<char> sample(1, 2, 'a', 'b');
return 0;
}
[EDIT]: Added std::forward, added missing include for utility [编辑]:添加了 std::forward,为实用程序添加了缺失的包含
Assuming that T could be anything, even something quite large or non-copyable, we'd want to:假设 T 可以是任何东西,甚至是非常大或不可复制的东西,我们想要:
preserve efficiency with perfect forwarding.通过完美转发保持效率。
check types.检查类型。
std::initializer_list
satisfies 2 but not 1. std::initializer_list
满足 2 但不满足 1。
Simple variadic template expansion satisfies 1 and not 2.简单的可变参数模板扩展满足 1 而不是 2。
This solution uses variadic template expansion and enable_if
to enforce type compatibility.此解决方案使用可变参数模板扩展和enable_if
来强制类型兼容性。
#include <vector>
#include <utility>
#include <string>
namespace detail
{
constexpr bool all()
{
return true;
}
template<class...Rest>
constexpr bool all(bool b, Rest...rest)
{
return b and all(rest...);
};
}
template<class T>
class A
{
public:
using value_type = T; // say
template<class...Rest,
std::enable_if_t<detail::all(std::is_convertible<Rest, value_type>::value...)>* = nullptr>
A(int a, int b, Rest&&...rest)
: a_(a), b_(b)
{
this->fill(std::forward_as_tuple(std::forward<Rest>(rest)...),
std::make_index_sequence<sizeof...(Rest)>());
}
private:
template<class Tuple, std::size_t...Is>
void fill(Tuple&& t, std::index_sequence<Is...> seq)
{
data_.reserve(seq.size());
using expand = int[];
void(expand{ 0,
(data_.push_back(std::move(std::get<Is>(t))), 0)...
});
}
private:
int a_, b_;
std::vector<value_type> data_;
};
int main()
{
using namespace std::literals;
auto a = A<double>(1, 2, 4.3, 5.5, 6.6);
auto b = A<std::string>(1, 2, "the", "cat"s, "sat on the mat");
// error: no matching constructor...
// auto err = A<std::string>(1, 2, "the", "cat"s, 0.1);
}
Here you go:干得好:
#include <iostream>
#include <vector>
template<class T>
struct V
{
V(int n, std::initializer_list<T> l)
: data(l)
{
(void) n;
}
std::vector<T> data;
};
int main()
{
V<int> v(0,{1,2,3});
}
This is not a perfect example since one needs to construct an object with the weird syntax (n, {optional, arguments, of, same, type})
but it does provide wanted behavior.这不是一个完美的例子,因为需要用奇怪的语法(n, {optional, arguments, of, same, type})
构造一个对象,但它确实提供了想要的行为。
The following example is similar to fr3nzy90's, but with the coming C++17 it will allow automatic deduction of T
from the constructor arguments:下面的例子类似于 fr3nzy90 的,但随着即将到来的 C++17,它将允许从构造函数参数中自动推导出T
:
template <class T>
class MyContainer {
private:
std::vector<T> data;
public:
// Take the first T value explicitly so it can be used to deduce
// T from the constructor arguments (C++17 feature).
template <class... Ts>
MyContainer(int a, int b, T const & tval, Ts const &... tvals) :
data{tval, tvals...} {
…
}
// Special case, empty list, no implicit type deduction, because
// there is no T value to deduce it from.
MyContainer(int a, int b) {
…
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.