"Ambigous"等效转换 - 我可以让编译器只选择任何一个吗?
"Ambigous" equivalent conversions - can I make the compiler just choose any?
我有一个模拟指针行为的类模板,当强制转换为任何指针类型时,将指针返回到给定的存储内存位置。
它具有转换为多种类型(intptr_t、模拟的本机指针等)的运算符,就像指针的正常情况一样,它返回在这种情况下真实指针将返回的值。
MockPointer<int> TestIntPointer;
MockPointer<int> TestIntPointer2;
int* a = nullptr;
ASSERT_TRUE(TestIntPointer == a);
ASSERT_TRUE(TestIntPointer == TestIntPointer2);
没有bool operator==(MockPointer<T> rhs)
我在第二个断言时收到错误:
Multiple markers at this line
- operator==(int*, int*) <built-in>
- candidates are:
- in expansion of macro 'ASSERT_TRUE'
- operator==(intptr_t {aka long int}, intptr_t {aka long int}) <built-in>
- operator==(intptr_t {aka long int}, int) <built-in>
- operator==(int, intptr_t {aka long int}) <built-in>
- operator==(int, int) <built-in>
ambiguous overload for 'operator==' (operand types are '{anonymous}::MockPointer<int> and '{anonymous}::MockPointer<int>)
使用运算符时,第一个断言失败:
- in expansion of macro 'ASSERT_TRUE'
- ambiguous overload for 'operator==' (operand types are '{anonymous}::MockPointer<int>' and 'int*')
- candidates are:
- operator==(int*, int*) <built-in>
我知道有很多方法可以转换变量并进行比较!为了进行比较,它们的工作方式都相同!我可以以某种方式强制编译器选择第一个可用的转换并使用它,而不是抱怨它无法决定是否应该在茶中加入糖和牛奶,或者更确切地说是牛奶和糖?
编辑:完整代码(运算符==行接近文件的2/3,有些被注释掉了):
#pragma once
#include <stdint.h> //zapewnia stdint_t, specjalny int do przechowywania wskaźników.
#include "api/utils/tinyutils.h"
#include "api/standard_exceptions.h"
namespace Api {
/**
* ShmPointer
* Klasa zachowująca się jak zwykły wskaźnik ale działająca dla w pamięci współdzielonej.
*
* Sposób użycia:
* Każda instancja (wariant) pamięci współdzielonej tworzona jest bądź pobierana przez ShmProvider
* W szczególności określona instancja to
*
* ShmProvider<typ_shm, klucz_shm> MyShmProvider;
*
* Dla niej generujemy template pointerów do wszystkiego, co można w tejże pamięci znaleźć:
*
* template <class T>using MyShmPointer = ShmPointer<T,MyShmProvider>;
*
* Potem już tylko:
* MyShmPointer<Grupa> gr = &(MyShmProvider::Base->Grupy[5]); //cast zwykłego wskaźnika na ShmPointer
*
* MyShmProvider::Base->AktywnaGrupa = gr; //przypisanie jednego ShmPointer do drugiego, leżącego w SHM
*
* // w zupełnie innym programie
* display(MyShmProvider::Base->AktywnaGrupa->kolor); //odczytanie wartości po wskaźniku
*/
template<class T, class ShmProvider>
class ShmPointer
{
private:
int offset = -1;
bool IsEmpty() const {
return offset == -1;
}
T* MyAddress() {
if(unlikely(IsEmpty()))
return nullptr;
return (T*)((char*)ShmProvider::Base + offset);
}
T* Add(int count) {
return reinterpret_cast<T*>((char*)MyAddress() + count*sizeof(T));
}
public:
ShmPointer() = default;
//Konstruktor na podstawie wskaźnika.
ShmPointer(T* shmaddr) : offset((char*)shmaddr - (char*)ShmProvider::Base) {
}
// Operatory rzutowania
//Cast na typ "wskaźnik do T"
operator T*() {
return MyAddress();
}
//Cast na typ boolean
operator bool() {
return !IsEmpty();
}
//rzutowanie na int
operator intptr_t() {
return (intptr_t) MyAddress();
}
// Standardowe operatory (znaczki)
//Dereferencja na pole
T* operator->()
{
if(IsEmpty()) throw( NullPointerDereferenceException(LOCATION) );
return MyAddress();
}
//Dereferncja wprost
T& operator*()
{
if(IsEmpty()) throw( NullPointerDereferenceException(LOCATION) );
return *(MyAddress());
}
//Przypisanie
T* operator=(T* shmaddr)
{
if(shmaddr==nullptr)
{
offset=-1;
return nullptr;
}
offset = (char*)shmaddr - (char*)ShmProvider::Base;
return MyAddress();
}
//Dereferencja nawiasami
T& operator[](int ndx)
{
if(IsEmpty()) throw(NullPointerDereferenceException(LOCATION));
return (T&) *(Add(ndx));
}
T* operator+(int ndx)
{
if(IsEmpty())
return nullptr;
return Add(ndx);
}
T* operator-(int arg)
{
if(IsEmpty())
return nullptr;
return Add(-arg);
}
intptr_t operator-(T* arg)
{
if(MyAddress() == nullptr){ return 0; }
return (intptr_t)((char*)MyAddress() - (char*)arg);
}
bool operator!()
{
return offset == -1;
}
bool operator==(const Api::ShmPointer<T, ShmProvider>& rhs) const {
return offset == rhs.offset;
}
bool operator==(const std::nullptr_t rhs) const {
return IsEmpty();
}
/*
bool operator==(const T* rhs) const {
return (MyAddress() == rhs);
}
*/
/*
bool operator!=(const ShmPointer<T, ShmProvider>& rhs) const {
return !(*this == rhs);
}
*/
bool operator!=(const std::nullptr_t rhs) const {
return !(*this == rhs);
}
/*
bool operator!=(const T* rhs) const {
return !(MyAddress() == rhs);
}
*/
T* operator++()
{
if(IsEmpty())
return nullptr;
offset += sizeof(T);
return MyAddress();
}
T* operator++(int)
{
if(IsEmpty())
return nullptr;
T* dummy = MyAddress();
offset += sizeof(T);
return dummy;
}
T* operator--()
{
if(IsEmpty()) return nullptr;
offset -= sizeof(T);
return MyAddress();
}
T* operator--(int)
{
if(IsEmpty()) return nullptr;
T* dummy = MyAddress();
offset -= sizeof(T);
return dummy;
}
};
}
这是由于大量的转换运算符和通过构造函数的隐式转换。您应该能够通过以下方式避免歧义
-
提供完美匹配的比较运算符
bool operator==(const MockPointer<T>& rhs);
-
使构造函数显式
T*
explicit MockPointer(T*);
我在 http://coliru.stacked-crooked.com/a/73300327b4fcfac8 上做了一个你可以玩的活例子;尝试从构造函数中删除explicit
关键字,它重现了你在问题和评论中描述的问题。允许编译器为隐式转换留出太多的自由度通常会导致歧义,因为编译器有太多方法来实现函数调用。
删除一个或多个隐式转换也可能获得一些结果。
相关文章:
- 高级选择排序 - 在一次迭代中搜索两个元素
- 哗啦��错误:无法识别任何一组可以驱动指定关节的控制器
- 如何允许用户选择何时停止三列中的每一列的旋转
- 当通过常量和不是字符串的最佳选择时,是否有任何情况?
- 如何修复列表视图中的错误?,封装控件时无法选择任何项
- C++ gtkmm:文件选择器对话框不适用于任何驱动器
- 匹配匹配任何内容,直到'%'不后跟'%',后跟一组字符
- 一种类型特征,标识哪个类提供通过重载解析选择的函数
- 我如何使一行代码可以选择,但在已经选择过一次后不重新选择
- 在 C++14 中,是否有一种优雅的解决方案可以在可变参数模板中选择可调用和不可调用的类型
- __restrict__ shared_ptr和一般的任何类
- 有没有一种方法可以在基于枚举的可变参数模板函数之间进行选择,这比将函数包装在结构中更简单
- OpenCV将一种颜色转换为任何其他颜色
- 以一种方式使用字符串选择(如果语句)
- 选择是一种奇异的链表
- QTreeWidget::currentItem没有选择任何内容时返回的内容
- 在编程中,这两项任务中的任何一项都有算法方法吗
- "Ambigous"等效转换 - 我可以让编译器只选择任何一个吗?
- 如何测试使用 MPI 调用的 CC++ 代码:是否有任何一组我可以使用的模拟函数
- 如何将std::string转换为构造函数中几种类型中的任何一种