【发布时间】:2021-01-26 16:51:27
【问题描述】:
您可以在下面找到一个精简的、可重复的示例,说明我正在尝试完成的工作。我的用例是一个自定义容器类模板。该类有一个构造函数,采用元素类型的std::initializer_list。对于容器包含std::unique_ptr<OwnedType> 类型元素的情况,我想启用另一个构造函数,该构造函数采用std::initialiser_list<typename std::unique_ptr<OwnedType>::pointer> aka std::initializer_list<OwnedType*>。我的方法是使用 SFINAE 禁用该构造函数,以防我的容器类的元素类型没有名为 pointer 的类型,根据我对 @ 下列出的示例的理解,这应该是一个有效的 SFINAE 失败案例并且没有编译错误987654321@
#include <vector>
#include <memory>
template <typename T>
struct MyVector
{
/** General initializer list constructor */
MyVector (std::initializer_list<T> il) : vector (il) {}
/** Constructor for the case MyVector<std::unique_ptr<SomeType>>.
Should be treated as an SFINAE failure for non unique_ptr types
*/
template <typename OwnedTypePtr = typename T::pointer>
MyVector (std::initializer_list<OwnedTypePtr> il)
{
vector.reserve (il.size());
for (auto* ptr : il)
vector.emplace_back (ptr);
}
std::vector<T> vector;
};
template <typename T>
using UniqueVector = MyVector<std::unique_ptr<T>>;
int main()
{
UniqueVector<int> uv { new int (0), new int (1), new int (2) };
MyVector<int> v { 0, 1, 2 };
return 0;
}
(在godbolt.org上使用clang 10.0.0时编译失败)
我似乎在这里理解了一些错误,因为 clang 抱怨说
type 'int' cannot be used prior to '::' because it has no members
in instantiation of template class 'MyVector<int>' requested here
MyVector<int> v { 0, 1, 2 };
所以我预期的有效 SFINAE 失败案例被解释为编译错误。我很感兴趣为什么上面的代码不是有效的 SFINAE 构造以及如何正确执行它的解决方案。
================================================ =======================
编辑:最初的问题可以通过@super给出的答案来解决。不幸的是,现在在我的现实世界场景中,我遇到了std::complex 值向量的问题,这些向量由标量值初始化,在这些更改之前有效。调整示例
#include <vector>
#include <memory>
#include <complex>
template <typename T>
struct MyVector
{
/** General initializer list constructor */
MyVector (std::initializer_list<T> il) : vector (il) {}
/** Constructor for the case MyVector<std::unique_ptr<SomeType>>.
Should be treated as an SFINAE failure for non unique_ptr types
*/
template <typename U = T, typename OwnedTypePtr = typename U::pointer>
MyVector (std::initializer_list<OwnedTypePtr> il)
{
vector.reserve (il.size());
for (auto* ptr : il)
vector.emplace_back (ptr);
}
std::vector<T> vector;
};
template <typename T>
using UniqueVector = MyVector<std::unique_ptr<T>>;
int main()
{
UniqueVector<int> uv { new int (0), new int (1), new int (2) };
MyVector<std::complex<int>> v { 0, 1, 2 };
return 0;
}
我不明白为什么编译器在这里选择新的唯一 ptr 重载,据我所知,std::complex 没有名为 pointer 的公共类型。
【问题讨论】:
-
将
unique_ptr放入initializer_list是没有意义的,因为您只有const对其成员的访问权限;你不能离开他们。 -
我不是想将
unique_ptr放在initializer_list中,而是想将指向unique_ptr的底层类型的指针放入列表中