当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《g++和clang++-删除由重载转换运算符歧义获取的指针》经验,为你挑选了1个好方法。

我试图通过制作这个指针包装器(替换原始指针)来发布此代码作为这个问题的答案.这个想法是委托const给它的指针,以便filter函数不能修改值.

#include 
#include 

template 
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> filter(std::vector> const& vec)
{
    //*vec.front() = 5; // this is supposed to be an error by requirement
    return {};
}

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

Visual C++ 12和14编译时没有错误,但GCC和Coliru的Clang声称存在歧义.我期待他们选择非常量std::vector::front超载然后my_pointer::operator T* &,但没有.为什么?



1> T.C...:

[expr.delete]/1:

操作数应该是指向对象类型或类类型的指针.如果是类类型,则操作数在上下文中被隐式转换(Clause [conv])为指向对象类型的指针.

[转]/5,强调我的:

某些语言结构需要转换为具有适合于该构造的一组指定类型之一的值.出现在这样的上下文中e的类类型的表达式E被称为上下文隐式转换为指定类型T,并且当且仅当e可以隐式转换T为如下确定的类型时才是格式良好的 :E搜索非显式的转换函数,其返回类型cv T或引用cv T ,使得T由上下文允许的.应该只有一个这样的T.

在你的代码中,有两个这样的Ts(int *const int *).因此,在您进行超载分辨率之前,它是不正确的.


请注意,C++ 11和C++ 14之间的区域有所变化.C++ 11 [expr.delete]/1-2说

操作数应具有指向对象类型的指针,或具有指向对象类型的指针的单个非显式转换函数(12.3.2)的类类型.[...]

如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,[...]

如果按字面意思读取,将允许您的代码并始终调用operator const int*() const,因为int* &它是引用类型,而不是指向对象类型的指针.在实践中,实现将转换函数视为"引用指向对象的指针" operator int*&(),然后拒绝代码,因为它具有多个合格的非显式转换函数.

推荐阅读
LEEstarmmmmm
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有