使用别名模板时,无法将“std :: unique_ptr”分配给clang中的基类 [英] Can't assign a `std::unique_ptr` to a base class in clang when using an alias template

查看:543
本文介绍了使用别名模板时,无法将“std :: unique_ptr”分配给clang中的基类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码在gcc 4.9.3和clang 3.7.1上编译和运行。

The following code compiles and runs just fine on gcc 4.9.3 and 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>());
}

/ code>到 #if 1 ,gcc编译,但clang不会:

However, if we change the #if 0 to #if 1, gcc compiles, but clang does not:

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

在此上下文中使用别名模板有什么问题?

What's the problem with using the alias template in this context? Or, if gcc is more permissive than it should be, why is that the case?

推荐答案

这是 CWG问题1244


14.4 [temp.type]段落1中的示例读取了重要部分,

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;

并说 y z 有相同的类型。

这将只有当别名模板 Z 被认为等同于类模板 Y 。但是,14.5.7 [temp.alias]仅描述了别名模板的特殊化,而不是别名模板本身的等价。

This would only be true if alias template Z were considered to be equivalent to class template Y. 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.

我们可以将您的例子缩减为:

We can reduce your example down to:

std::unique_ptr<Base<double, Buz>> f = 
    std::make_unique<Base<double, Bar>>();

如果且仅当 Buz Bar 被视为等同。 gcc认为他们是,ang认为他们不是。这仍然是一个开放的问题,实际的答案是什么。

This is well formed if and only if Buz and Bar are considered equivalent. gcc thinks they are, clang thinks they aren't. It's still an open question as to what the actual answer is.

这篇关于使用别名模板时,无法将“std :: unique_ptr”分配给clang中的基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆