代码之家  ›  专栏  ›  技术社区  ›  Nelfeal

使方法显式,但友元类除外

  •  1
  • Nelfeal  · 技术社区  · 6 年前

    更准确地说,我有一个相对简单的类模板,其实例应该可以转换为其他类型( int 在整个问题中,为了简单起见)。但是,我希望此转换在默认情况下是显式的,但仍然允许它对另一个类(即作为模板参数传递的类)是隐式的。没有这最后一部分,这就是它的样子:

    template<typename T>
    class A {
    public:
        A(int i) : i(i) {}
        explicit operator int() const {
            return i;
        }
    
    private:
        int i;
    };
    

    A a(2); int i = a; 方法内部 T (这应该是一个类)。

    我的第一个想法是使用friend声明并声明转换运算符的私有重载。但是,重载仅仅基于 explicit 是不允许的。所以我试着用 const 相反,它起了作用:

    template<typename T>
    class A {
    public:
        A(int i) : i(i) {}
        explicit operator int() { // Public non-const
            return i;
        }
    
    private:
        int i;
    
        operator int() const { // Private const
            return i;
        }
    
        friend T;
    };
    

    ... 直到它不起作用。这只在使用非常量时起作用 A s、 虽然我不打算用 const A s、 我仍然希望它在所有情况下都能起作用。注意,如果公共过载是 而私人的不是,这只在使用 常量A

    Here is a demo 显示它在哪些情况下起作用或不起作用。

    我想用 volatile ( demo 一个 s。

    有更好的办法吗?更普遍地说,有没有办法解决第一句话中的问题?

    0 回复  |  直到 6 年前
        1
  •  1
  •   Nelfeal    6 年前

    显然没有令人满意的解决办法。这个 volatile volatile A s、 额外的 const_cast 解决了这个问题。

    template<typename T>
    class A {
    public:
        A(int i) : i(i) {}
        explicit operator int() const {
            return i;
        }
    
    private:
        int i;
    
        operator int() const volatile {
            return static_cast<int>(const_cast<A const&>(*this));
            // or just
            // return i;
        }
    
        friend T;
    };
    

    Demo

    using )而不是一个推动的基础。这可能就是为什么该语言不提供根据执行转换的类或块来更改转换语义的方法。