【问题标题】:operator >> is not defined why?运算符>>没有定义为什么?
【发布时间】:2019-10-29 21:08:46
【问题描述】:

我正在尝试帮助this question,我想我找到了一个不错的解决方案。但由于我需要的所有包装,它有点复杂。 我想重载operator>> 以允许简单的链接符号。但它并没有像我预期的那样工作。

我能做到:

#include <functional>
#include <memory>

template<typename T>
class Object {
private:
    T* const ptr{ nullptr };
public:
    Object(T* ptr) noexcept : ptr(ptr) {}
    T* Get() const noexcept { return ptr; }
};

using MyObject = Object<int>;

template <typename T, typename MemFn>
auto fnc (T* ptr, MemFn memFn)
-> decltype(std::invoke(memFn, std::declval<T>())) {
    if (ptr) return std::invoke(memFn, *ptr);
    return nullptr;
}

int main() {
    std::unique_ptr<MyObject> myObjectPtr = std::make_unique<MyObject>(nullptr);
    [[maybe_unused]] int* optionalTarget = fnc(myObjectPtr.get(), &MyObject::Get);
}

不过,我想做

#include <functional>
#include <memory>

template<typename T>
class Object {
private:
    T* const ptr{ nullptr };
public:
    Object(T* ptr) noexcept : ptr(ptr) {}
    T* Get() const noexcept { return ptr; }
};

using MyObject = Object<int>;

template <typename T, typename MemFn>
auto operator>> (T* ptr, MemFn memFn)
-> decltype(std::invoke(memFn, std::declval<T>())) {
    if (ptr) return std::invoke(memFn, *ptr);
    return nullptr;
}

int main() {
    std::unique_ptr<MyObject> myObjectPtr = std::make_unique<MyObject>(nullptr);
    [[maybe_unused]] int* optionalTarget = myObjectPtr.get() >> &MyObject::Get;
}

什么有效,但我认为丑陋的是

#include <functional>
#include <memory>
#include <optional>

template<typename T>
class Object {
private:
    T* const ptr{ nullptr };
public:
    Object(T* ptr) noexcept : ptr(ptr) {}
    T* Get() const noexcept { return ptr; }
};

using MyObject = Object<int>;

template <typename T>
auto makeOptRef(T* ptr) -> std::optional< std::reference_wrapper<T>> {
    if (ptr) return std::ref(*ptr);
    return {};
}

template <typename T, typename MemFn>
auto operator>> (std::optional<std::reference_wrapper <T>> ptr, MemFn memFn)
-> std::optional<std::reference_wrapper<std::remove_pointer_t<decltype(std::invoke(memFn, std::declval<T>()))>>> {
    if (ptr) return makeOptRef(std::invoke(memFn, *ptr));
    return {};
}

int main() {
    std::unique_ptr<MyObject> myObjectPtr = std::make_unique<MyObject>(nullptr);
    std::optional<std::reference_wrapper<MyObject>> myObjOptRef = makeOptRef(myObjectPtr.get());

    std::optional<std::reference_wrapper<int>> optionalTarget = myObjOptRef >> &MyObject::Get;

    [[maybe_unused]] int output = (optionalTarget) ? optionalTarget->get() : -1;
}

【问题讨论】:

  • 您显示的代码与您的描述不一致 - 两个示例都无法编译,更不用说“工作”了。如果一个对您有用,而另一个对您无效,则说明是您的实际代码与您发布的代码之间的差异。阅读提供minimal reproducible example。此外,除了该类的实例(或指向实例的指针)之外,不能在该类的实例(或指向实例的指针)上调用或调用该类的成员函数 - 如果这是强制的,则行为未定义。
  • "重载的operator&gt;&gt;必须至少有一个类或枚举类型的参数"
  • 我认为你也在过度使用auto。将它用于std::unique_ptr&lt;MyObject&gt; 是一回事,但用于int *?这实际上使阅读代码变得更加困难......我不得不花费心理周期来推断 optionalTarget 是什么类型。
  • 美国汽车协会?!
  • @MarkStorer Almost Always Auto

标签: c++ operator-overloading


【解决方案1】:

任何指针类型都是内置类型,指向成员的指针也是如此。您正在尝试为两种内置类型重载运算符,这只是一个非首发。至少一个参数必须是用户定义的类型,或者是对它的引用。

您可以通过传递 T&amp; 而不是 T* 来使其工作。

【讨论】:

  • 嗯,我很害怕...如果返回 nullptr,传递 T 引用会导致问题。那么我将需要一个 std::optional 再次......它需要一个 std::reference_wrapper ......我又回到了我之前的糟糕代码......有没有办法获得与运营商的链接?
  • @JHBonarius - 好吧,你总是可以假设T&amp; 指的是一个智能指针对象。那应该是用户定义的类型。然后链接指针而不调用get()
  • 是的,所以原始问题的 OP 正在使用遗留代码......没有任何智能指针......
  • 我仍在努力解决这个问题。对于原始指针,我如何才能实现这一点……当 T* = nullptr 时,如何处理 T&?我找不到比 std::optional 更好的解决方案。所以我不能接受你的回答,因为“你可以通过传递 T& 而不是 T* 来让它工作。”对我来说不是真的......
  • @JHBonarius - 您没有义务接受任何答案。
猜你喜欢
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
相关资源
最近更新 更多