Question: I've just run into curious std::experimental::propagate\_const bug.
The following snippet demonstrates the problem

```
#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;
};

```

So you can't just replace unique\_ptr with propagating unique\_ptr because sometimes your forward declarations will break it.

**I would appreciate if someone would explain to me why compilation fails in current implementation of propagate\_const**. 
It has something to do with 

```
typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;

```

Because workaround is:

```
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;

```

Tested compilers: clang, gcc.

P.S. I wonder whether compiler devs know about it or not.

Answer: 
1. Instantiating a standard library template with an incomplete type is generally prohibited.
2. `std::map` is not an exception to that rule.
3. Querying `decltype(*std::declval<_Tp&>())` with `_Tp = std::unique_ptr<std::map<int, FWD>>` necessitates the instantiation of all associated classes of `_Tp` to look for potential friend `operator*` declarations.
4. Among those associated classes is `std::map<int, FWD>`.
5. Instantiation of `std::map<int, FWD>` invokes undefined behavior.
I've submitted a patch to propagate\_const that replaces the existing solution and address the issue like the above-proposed solution but that does not rely on SFINAE:

```
template<class U>
struct detect_element_type {
    using type = typename U::element_type;
};

template<class U>
struct detect_element_type<U*> {
    using type = U;
};

using element_type = typename detect_element_type<T>::type;

```