以下代码在 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 issue 1244 :
The example in 14.4 [temp.type] paragraph 1 reads in significant part,
template<template<class> class TT> struct X { }; template<class> struct Y { }; template<class T> using Z = Y<T>; X<Y> y; X<Z> z;
and says that
y
andz
have the same type.This would only be true if alias template
Z
were considered to be equivalent to class templateY
. However, 14.5.7 [temp.alias] describes equivalence only for specializations of alias templates, not for the alias templates themselves. Either such rules should be specified, which could be tricky, or the example should be deleted.
我们可以将您的示例简化为:
std::unique_ptr<Base<double, Buz>> f =
std::make_unique<Base<double, Bar>>();
当且仅当 Buz
和 Bar
被认为是等价的时,这是良构的。 gcc 认为它们是,clang 认为它们不是。关于实际答案是什么,这仍然是一个悬而未决的问题。
关于c++ - 使用别名模板时无法将 `std::unique_ptr` 分配给 clang 中的基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39843027/