使方法明确,除了朋友 类

Make method explicit except for friend classes

我正在尝试创建一个默认情况下显式的转换运算符,除了一些指定的 classes。

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

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

private:
    int i;
};

现在,我希望能够在 T(应该是 class)的方法中编写类似 A a(2); int i = a; 的内容。

我的第一个想法是利用友元声明并声明转换运算符的私有重载。但是,不允许仅基于 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;
};

...直到没有。这仅在使用非常量 As 时有效,虽然我不打算使用 const As,但我仍然希望它在所有情况下都能正常工作。请注意,如果 public 重载是 const 而私有重载不是,则这仅适用于 const As.

Here is a demo 显示它在哪些情况下有效或无效。

我想过使用volatiledemo),虽然它使它变得更好,但仍然导致同样的问题:它仅在使用非易失性时有效As.

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

显然没有令人满意的解决方案。 volatile 选项似乎是最实用的,虽然它不太适用于 volatile As,但额外的 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

正如 Sneftel 在评论中所述,访问权限往往是在拉动的基础上 (using) 而不是推送的基础上授予的。这可能就是为什么该语言没有提供一种方法来根据 class 或块执行转换来更改转换语义。