C++ 运算符的隐式转换==

问题描述 投票:0回答:1

我无法理解为什么一个模板实例化在我的代码中有效,而另一个却不能。

我正在使用我创建的这个类模板:

template <typename T>
struct Allocated {
public:
    const T& get() const& {
        return *ptr.get();
    }
    T& get() & {
        return *ptr.get();
    }
    T&& get() && {
        return std::move(*ptr.get());
    }

    operator T& () & {
        return *ptr.get();
    }

    operator const T& () const & {
        return *ptr.get();
    }

    operator const T () && {
        return std::move(* ptr.get());
    }

    template <typename U>
    Allocated(const U& u) : ptr(std::make_unique<T>(u)) {}
    template <typename U>
    Allocated(U&& u) : ptr(std::make_unique<T>(std::move(u))) {}
    Allocated()  = delete;
    Allocated(const Allocated& other) : Allocated(other.get()) {};
    Allocated& operator=(const Allocated& other) {
        ptr = std::make_unique<T>(*other.ptr);
    }
    Allocated(Allocated&& other) : Allocated(other.get()) {};
    Allocated& operator=(Allocated&& other) {
        ptr = std::move(other.ptr);
        return *this;
    }
    ~Allocated() = default;
protected:
    std::unique_ptr<T> ptr;
};

这个代码可以工作

    Allocated<int> u = 7;
    bool k1 = u.get() == u.get();
    bool k2 = u == u; // this works fine and calls `operator T&`

虽然这不是

    Allocated<std::string> u = "test";
    bool k1 = u.get() == u.get();
    bool k2 = u == u; // error here

问题1:为什么int调用

operator T&
而不是std::string?

问题2:如何修复任意类型的问题?我不想在

operator==
中定义
Allocated
,它应该适用于其他运算符,例如
Allocated<int>.operator>(Allocated<int>)

c++ implicit-conversion
1个回答
0
投票

此代码的问题在于它依赖于

operator ==
为隐式类型转换提供上下文。它适用于
int
,因为有一个内置的
bool operator ==(int, int)
候选者。当编译器检查这个候选函数时,它知道参数的类型,并且能够通过调用
Allocated::operator int const &
来执行隐式类型转换。但是它不适用于
string
,因为
string
的对应运算符实际上是一个模板(因为
std::string
std::basic_string
的别名),因此当编译器检查此候选者时,它不知道参数类型,需要推断它们。

以下简化示例说明了差异:

template <typename T>
struct Allocated
{
    operator T const & () const;
};
struct NotTemplate{};

bool operator ==(NotTemplate const &, NotTemplate const &);

Allocated<NotTemplate> not_template{};
bool not_template_cmp{not_template == not_template}; // ok

template<typename Dummy>
struct Template{};

template<typename Dummy>
bool operator ==(Template<Dummy> const &, Template<Dummy> const &);

Allocated<Template<void>> _template{};
bool _template_cmp{_template == _template}; // error, no matching...
template<typename Dummy>
struct Template{};

template<typename Dummy>
bool operator ==(Template<Dummy> const &, Template<Dummy> const &);

bool operator ==(Template<void> const &, Template<void> const &);

Allocated<Template<void>> _template{};
bool _template_cmp{_template == _template}; // ok
© www.soinside.com 2019 - 2024. All rights reserved.