我希望编写一个可变参数工厂函数来转发可变数量的参数(相同类型)来构造和填充 std::vector
。但是我不确定如何从“完美转发”机制中提取元素的类型,因此由编译器自动推导此类型,并使用它来设置 vector 的类型。
本质上:
template <typename T>
struct Object { T x {}; };
Object<int> x1 {1};
Object<int> x2 {2};
auto collection = make_objects(x1, x2, Object<int>(3));
// 'collection' is a std::vector<Object<int>> with elements that are copies of x1, x2, and the third rvalue parameter.
// note that `make_objects` deduced all types it needed.
我正在使用 C++20 - 完整代码 here .
让我们从基本的具体结构开始:
struct Object {
int x {};
};
我希望使用 std::vector
创建任意数量的集合。作为容器。我有一个名为 make_objects
的“工厂”函数它通过左值和/或右值获取可变数量的 Object 实例,并将它们完美转发到 vector 的 emplace_back()
成员函数:
template <typename... Args>
auto make_objects(Args&&... args) {
std::vector<Object> vec;
vec.reserve(sizeof...(Args));
(vec.emplace_back(std::forward<Args>(args)), ...);
return vec;
}
这意味着客户端代码大多不知道集合类型(或者至少可以依赖 auto
),并且可以执行以下操作:
int main() {
Object x1 {1};
Object x2 {2};
auto objects = make_objects(x1, x2, Object(3));
for (auto o: objects) {
std::cout << o << '\n';
}
}
到目前为止一切顺利。
现在我想做我的Object
通过将其转换为模板更通用,因此我将其更改为:
template <typename T>
struct Object {
T x {};
};
此时我对如何编写make_objects
感到困惑工厂功能。我的第一次尝试是:
template <typename T, typename... Args>
auto make_objects(Args&&... args) {
std::vector<T> vec; // how to specify this type?
vec.reserve(sizeof...(Args));
(vec.emplace_back(std::forward<Args>(args)), ...);
return vec;
}
除非使用显式 T
调用,否则不会编译。 ,即make_objects<Object<int>>
。否则类型 T 不可推导。
有没有一种方法可以实现这种完美的转发,以便可以提取正在转发的同类类型并在转发函数中使用?
请注意,我希望避免使用以下类型的语法:
make_objects<int>(x, ...)
- 我希望从参数中推断出对象的类型,但它们至少都是相同的类型(也许 std::same_as
或 std::convertible_to
可以在这里使用来强制执行?)。
make_objects({x, ...})
- 我不想在这种情况下使用初始化列表,因为最终我需要参数是非常量的,因为为了清楚起见,我省略了预期的副作用。
我一直在学习Homogeneous function parameter packs但这似乎遇到了同样的问题,因为如果Obj
一切正常是一个具体的类,但没有提供关于如何处理模板化 Obj<T>
的线索(我已经注意到) .
最佳答案
make_objects
可以简单地是:
template <typename... Args>
auto make_objects(Args&&... args) {
// use the std::vector deduction guide:
return std::vector{std::forward<Args>(args)...};
}
然后,这将起作用:
int main() {
Object x1 {1};
Object x2 {2};
auto objects1 = make_objects(x1, x2);
//auto objects2 = make_objects(x1, x2, Object{3}); // C++17
auto objects2 = make_objects(x1, x2, Object(3));
for (auto o: objects2) {
std::cout << o << '\n';
}
}
如果您希望 Object{3}
在 C++17 中工作,请添加推导指南:
template<class T> Object(T) -> Object<T>;
关于c++ - 如何从具有同构模板类型参数的完美转发函数中提取模板类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75569524/