我有一个模板化函数,它接受多个元素,可能还有参数化类型的初始值。如果没有提供初始值,则假定此类型有默认构造函数。
在此函数中,我声明std::vector
给定数量的元素和分配给它们的初始值。
只要模板类型不是unique_ptr
:
#include <memory>
#include <vector>
using namespace std;
template <class T>
void define_vector(size_t size, const T& init_val=T())
{
vector<T> sample(100, init_val);
}
int main()
{
define_vector<int>(100); //<-- this works
define_vector<unique_ptr<int> >(100); //<-- this does not
return 0;
}
据我所知,它试图复制unique_ptr
这是不允许的(已删除的构造函数)。但有什么方法可以解决这个问题吗?
我当然可以定义2个版本的函数 - 一个用于,另一个没有初始值作为参数。但这是唯一的方法吗?
更新:澄清明显的误解。我知道使用not-default unique_ptr
时代码没有意义/不应该编译。我想到的是以下内容。假设有一个类Foo
只有显式构造函数,它将int
值作为参数。因此
define_vector<Foo>(100); //does not make sense and does not compile
define_vector<Foo>(100, Foo(42)); //makes sense and compiles.
然而:
//does not make sense and does not compile
define_vector<unique_ptr<int> > (100, std::make_unique<int>(42));
//does make sense but still does not compile
define_vector<unique_ptr<int> > (100);
那么可以在不诉诸函数重载的情况下使第二种情况发挥作用吗?
答案 0 :(得分:1)
创建一个unique_ptr
数组是没有意义的,其中所有指针都具有相同的值(然后它们不会唯一),但值{{1}除外}。因此,接受任意初始值的函数对nullptr
无意义。
我当然可以定义2个版本的函数 - 一个用于,另一个没有初始值作为参数。但这是唯一的方法吗?
这是一种简单的方法,所以这是一个好方法。它甚至可能是最简单的方式,我不打算考虑是否有另一种方式。
我可以使用单个函数来获取初始值,或者使用默认构造函数(如果存在)
当你有C ++ 17时,这是可能的:
unique_ptr
问题是,是否有更好的方式?
不,我不这么认为。上面的内容不如重载,因为它允许传递初始参数,但是它会被静默忽略,而当给出非可复制类型的第二个参数时,重载方法会因为错误而失败。
答案 1 :(得分:1)
使用可变参数模板,您可以执行以下操作:
template <typename T, typename ... Ts>
void define_vector(size_t size, const Ts&... init_val)
{
std::vector<T> sample(100, init_val...);
// ...
}
注意:您可以添加一些SFINAE到约束init_val
,如果需要,最多只能有一个arg。
然后
define_vector<int>(5); // Call vector<int>(5) instead of your vector<int>(5, 0)
define_vector<int>(5, 42); // Call vector<int>(5, 42);
define_vector<unique_ptr<int> >(5); // Call vector<unique_ptr<int>>(5)