#include <iostream>
#include <type_traits>
 
enum class Mutability {Const, Non_Const};
 
template<Mutability T>
struct ConstMutability: std::true_type{};
 
template<>
struct ConstMutability<Mutability::Non_Const>: std::false_type{};
 
template <typename T, Mutability U>
class Obj
{
public:
    template <Mutability V, typename std::enable_if<
    std::is_same<ConstMutability<U>, ConstMutability<V>>::value || 
    (ConstMutability<V>::value && !ConstMutability<U>::value)
    >::type* = nullptr>
    class Ref
    {
    public:
        Ref() {std::cout << "Successfully created a Ref object" << std::endl;}
 
        friend class Obj;
    };
 
    Obj() {}
};
 
 
int main()
{
    Obj<int, Mutability::Const>::Ref<Mutability::Const> test1; //pass
    //Obj<int, Mutability::Const>::Ref<Mutability::Non_Const> test2; // fail
    Obj<int, Mutability::Non_Const>::Ref<Mutability::Const> test3; // pass
    Obj<int, Mutability::Non_Const>::Ref<Mutability::Non_Const> test4; // pass
}
				I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgplbnVtIGNsYXNzIE11dGFiaWxpdHkge0NvbnN0LCBOb25fQ29uc3R9OwoKdGVtcGxhdGU8TXV0YWJpbGl0eSBUPgpzdHJ1Y3QgQ29uc3RNdXRhYmlsaXR5OiBzdGQ6OnRydWVfdHlwZXt9OwoKdGVtcGxhdGU8PgpzdHJ1Y3QgQ29uc3RNdXRhYmlsaXR5PE11dGFiaWxpdHk6Ok5vbl9Db25zdD46IHN0ZDo6ZmFsc2VfdHlwZXt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIE11dGFiaWxpdHkgVT4KY2xhc3MgT2JqCnsKcHVibGljOgogICAgdGVtcGxhdGUgPE11dGFiaWxpdHkgViwgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8CiAgICBzdGQ6OmlzX3NhbWU8Q29uc3RNdXRhYmlsaXR5PFU+LCBDb25zdE11dGFiaWxpdHk8Vj4+Ojp2YWx1ZSB8fCAKICAgIChDb25zdE11dGFiaWxpdHk8Vj46OnZhbHVlICYmICFDb25zdE11dGFiaWxpdHk8VT46OnZhbHVlKQogICAgPjo6dHlwZSogPSBudWxscHRyPgogICAgY2xhc3MgUmVmCiAgICB7CiAgICBwdWJsaWM6CiAgICAgICAgUmVmKCkge3N0ZDo6Y291dCA8PCAiU3VjY2Vzc2Z1bGx5IGNyZWF0ZWQgYSBSZWYgb2JqZWN0IiA8PCBzdGQ6OmVuZGw7fQoKICAgICAgICBmcmllbmQgY2xhc3MgT2JqOwogICAgfTsKCiAgICBPYmooKSB7fQp9OwoKCmludCBtYWluKCkKewogICAgT2JqPGludCwgTXV0YWJpbGl0eTo6Q29uc3Q+OjpSZWY8TXV0YWJpbGl0eTo6Q29uc3Q+IHRlc3QxOyAvL3Bhc3MKICAgIC8vT2JqPGludCwgTXV0YWJpbGl0eTo6Q29uc3Q+OjpSZWY8TXV0YWJpbGl0eTo6Tm9uX0NvbnN0PiB0ZXN0MjsgLy8gZmFpbAogICAgT2JqPGludCwgTXV0YWJpbGl0eTo6Tm9uX0NvbnN0Pjo6UmVmPE11dGFiaWxpdHk6OkNvbnN0PiB0ZXN0MzsgLy8gcGFzcwogICAgT2JqPGludCwgTXV0YWJpbGl0eTo6Tm9uX0NvbnN0Pjo6UmVmPE11dGFiaWxpdHk6Ok5vbl9Db25zdD4gdGVzdDQ7IC8vIHBhc3MKfQ==