c++ - g++ 和 clang++ - 删除重载转换运算符歧义获取的指针

标签 c++ c++11 c++14 ambiguous

我试图发布此代码作为对 this question 的回答,通过制作这个指针包装器(替换原始指针)。这个想法是将 const 委托(delegate)给它的指针,这样 filter 函数就不能修改值。

#include <iostream>
#include <vector>

template <typename T>
class my_pointer
{
    T *ptr_;

public:
    my_pointer(T *ptr = nullptr) : ptr_(ptr) {}

    operator T* &()             { return ptr_; }
    operator T const*() const   { return ptr_; }
};

std::vector<my_pointer<int>> filter(std::vector<my_pointer<int>> const& vec)
{
    //*vec.front() = 5; // this is supposed to be an error by requirement
    return {};
}

int main()
{
    std::vector<my_pointer<int>> vec = {new int(0)};
    filter(vec);
    delete vec.front(); // ambiguity with g++ and clang++
}

Visual C++ 12 和 14 编译它没有错误,但是 GCC 和 Clang on Coliru声称存在歧义。我原以为他们会选择非常量 std::vector::front 重载,然后选择 my_pointer::operator T* &,但没有。这是为什么?

最佳答案

[expr.delete]/1:

The operand shall be of pointer to object type or of class type. If of class type, the operand is contextually implicitly converted (Clause [conv]) to a pointer to object type.

[conv]/5,强调我的:

Certain language constructs require conversion to a value having one of a specified set of types appropriate to the construct. An expression e of class type E appearing in such a context is said to be contextually implicitly converted to a specified type T and is well-formed if and only if e can be implicitly converted to a type T that is determined as follows: E is searched for non-explicit conversion functions whose return type is cv T or reference to cv T such that T is allowed by the context. There shall be exactly one such T.

在您的代码中,有两个这样的T(int *const int *)。因此,在您进行重载解析之前,它的格式是错误的。


请注意,在 C++11 和 C++14 之间,此区域发生了变化。 C++11 [expr.delete]/1-2 说

The operand shall have a pointer to object type, or a class type having a single non-explicit conversion function (12.3.2) to a pointer to object type. [...]

If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, [...]

如果从字面上看,这将允许您的代码并始终调用 operator const int*() const,因为 int* & 是引用类型,而不是指针对象类型。在实践中,实现也将转换函数视为“对对象指针的引用”,例如 operator int*&(),然后拒绝该代码,因为它具有不止一个符合条件的非显式转换函数。

关于c++ - g++ 和 clang++ - 删除重载转换运算符歧义获取的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34371901/

相关文章:

c++ - 获取 map C++ 的前 10 个值

c++ - 通过获取原子载荷来提升非原子载荷

c++ - 为什么在 std::move 到抛出函数后成员 unique_ptr<> 保持非空?

c++ - 创建我的第一个程序来显示生日

c++ - 在 NetBeans 中集成 Clang?

c++ - 一个字符串占多少字节?炭?

c++ - 创建内存文件

c++ - 位域的最小尺寸

c++ - FFMPEG中的av_opt_set是什么

c++ - 类范围内的变量模板