使用别名模板时,无法将"std::unique_ptr"分配给 clang 中的基类
Can't assign a `std::unique_ptr` to a base class in clang when using an alias template
下面的代码可以在gcc 4.9.3和clang 3.7.1上正常编译和运行
// std::unique_ptr
#include <memory>
// Template class for template-template arguments
template <typename Real>
struct Bar {};
// Base class
template <typename T,template <typename> class XX>
struct Base {};
// Derived class that operates only on Bar
template <typename Real>
struct Derived : public Base <Real,Bar> {};
// Holds the unique_ptr
template <typename T,template <typename> class XX>
struct Foo {
std::unique_ptr <Base <T,XX>> foo;
};
// Create an alias template
template <typename Real>
using Buz = Bar <Real>;
int main() {
#if 0
auto f = Foo <double,Buz> (); //Causes error!
#else
auto f = Foo <double,Bar> ();
#endif
f.foo = std::make_unique <Derived <double>> (Derived <double>());
}
但是,如果我们将#if 0
改为#if 1
, gcc可以编译,而clang不能:
g++ -std=c++14 test03.cpp -o test03_gcc
clang++ -std=c++14 test03.cpp -o test03_clang
test03.cpp:32:11: error: no viable overloaded '='
f.foo = std::make_unique <Derived <double>> (Derived <double>());
~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4/bits/unique_ptr.h:249:7: note:
candidate function not viable: no known conversion from
'unique_ptr<Derived<double>, default_delete<Derived<double>>>' to
'unique_ptr<Base<double, Buz>, default_delete<Base<double, Buz>>>' for
1st argument
operator=(unique_ptr&& __u) noexcept
^
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4/bits/unique_ptr.h:278:7: note:
candidate function not viable: no known conversion from 'typename
_MakeUniq<Derived<double> >::__single_object' (aka
'unique_ptr<Derived<double> >') to 'nullptr_t' for 1st argument
operator=(nullptr_t) noexcept
^
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4/bits/unique_ptr.h:357:19: note:
candidate function not viable: no known conversion from
'unique_ptr<Derived<double>, default_delete<Derived<double>>>' to
'const unique_ptr<Base<double, Buz>, default_delete<Base<double,
Buz>>>' for 1st argument
unique_ptr& operator=(const unique_ptr&) = delete;
^
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4/bits/unique_ptr.h:264:22: note:
candidate template ignored: disabled by 'enable_if' [with _Up =
Derived<double>, _Ep = std::default_delete<Derived<double> >]
typename enable_if< __and_<
^
1 error generated.
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1
在这种情况下使用别名模板有什么问题?或者,如果gcc比它应该的更宽松,为什么会这样?
这是CWG第1244期:
14.4 [temp.type]第1段中的例子是:
template<template<class> class TT> struct X { }; template<class> struct Y { }; template<class T> using Z = Y<T>; X<Y> y; X<Z> z;
表示
y
和z
具有相同的类型。只有当别名模板
Z
被认为等同于类模板Y
时,这才成立。然而,14.5.7 [temp.alias]只描述别名模板专门化的等价性,而不描述别名模板本身的等价性。要么应该指定这样的规则(这可能很棘手),要么应该删除示例。
我们可以把你的例子简化为:
std::unique_ptr<Base<double, Buz>> f =
std::make_unique<Base<double, Bar>>();
当且仅当Buz
和Bar
被认为是等价的,这是格式良好的。GCC认为是,clang认为不是。至于真正的答案是什么,这仍然是一个悬而未决的问题。
相关文章:
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- OpenSSL:当输出ptr为空时,BIGNUM的bin2bn不会分配新的BIGNUM
- 为什么在将常量 ptr 分配给常量引用时没有收到编译错误?
- 如何将函数 ptr 分配给函数 ptrs 数组(Arduino C++)
- 尝试为图像缓冲区分配内存时 ptr 值错误
- 当使用运算符 new 更改为其他内存的指向已分配内存的 ptr 时会发生什么
- 将现有值分配给智能ptr
- gcc共享ptr副本分配实现
- Boost Scoped Ptr-声明与分配
- 在另一个线程中分配唯一ptr的错误
- 分配const char *ptr数组参数?c++