propagate_const和forward声明

V. *_*nko 6 c++ c++17 c++-experimental

我刚刚遇到好奇的std :: experimental :: propagate_const错误.以下代码段演示了此问题

#include <memory>
#include <experimental/propagate_const>
#include <map>

class FWD;

//compiles
class A
{
    std::unique_ptr<FWD> m;
};

//compiles
class B
{
    std::experimental::propagate_const<std::unique_ptr<FWD>> m;
};

//compiles
class C
{
    std::unique_ptr<std::map<int, FWD>> m;
};

//does not compile!
class D
{
    std::experimental::propagate_const<std::unique_ptr<std::map<int, FWD>>> m;
};
Run Code Online (Sandbox Code Playgroud)

所以你不能只用传播的unique_ptr替换unique_ptr,因为有时你的前向声明会破坏它.

如果有人向我解释为什么编译在当前的propagate_const实现中失败,我将不胜感激.它与某些事情有关

typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
Run Code Online (Sandbox Code Playgroud)

因为解决方法是:

template <typename T, typename = void>
struct get_element_type
{
  using type = std::remove_reference_t<decltype(*std::declval<T&>())>;
};

template <typename T>
struct get_element_type<T, typename std::enable_if<!std::is_void<typename T::element_type>::value>::type>
{
  using type = typename T::element_type;
};

// Namespaces and class declaration...

using element_type = typename get_element_type<T>::type;
Run Code Online (Sandbox Code Playgroud)

经过测试的编译器:clang,gcc.

PS我想知道编译器开发者是否知道它.

T.C*_*.C. 5

  1. 通常禁止实例化具有不完整类型的标准库模板。

  2. std::map 也不是那个规则的例外。

  3. 查询时decltype(*std::declval<_Tp&>())_Tp = std::unique_ptr<std::map<int, FWD>>必须实例化所有关联的类_Tp以寻找潜在的好友operator*声明。

  4. 在这些相关的类中是std::map<int, FWD>

  5. 实例化std::map<int, FWD>调用未定义的行为。