使用友元函数来从多态类类型的信息?

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

我有一个关于使用嵌套多态类中友元函数来检索类型信息的问题。

我有以下的代码这表明我在做什么。鉴于两班,A<T>B<T>,我可以创造一个保存了AB运行时多态性包装。在实践中,这种包装可以容纳任何东西,包括具有相似的静态接口另一个模板类。

template<typename T>
struct A {
  T value_;

  A(T value) : value_(value) {}

  void sayHello() const {
    std::cout << "Hello from A! " << value_ << '\n';
  }
};

template<typename T>
struct B {
  T value_;

  B(T value) : value_(value) {}

  void sayHello() const {
    std::cout << "Hello from B! " << value_ << '\n';
  }
};

该包装来自肖恩家长运行时多态性的概念,但我有一个需要检索一些操作类型的信息。比如,也许我可以添加一个AB,但不是一个AC。基本上,如果我把模板化包装类中的朋友的功能,我可以把对象恢复到原来的类型。

class Wrapper {
private:
  class Concept {
  public:
    virtual ~Concept() = default;

    virtual void sayHello() const = 0;
  };

  template<typename T>
  class Model final
      : public Concept {
  private:
    T data_;

  public:
    Model(T data) : data_(data) {}

    virtual void sayHello() const override {
      data_.sayHello();
    }

  private:
    template<typename U>
    friend inline void doSomething(const Concept &lhs, const B<U> &rhs) {
      T x = static_cast<const Model<T> &>(lhs).data_;

      x.sayHello();
      rhs.sayHello();

      auto y = x.value_ + rhs.value_;

      std::cout << y << '\n';
    }
  };

  template<typename U>
  friend inline void doSomething(const Concept &lhs, const B<U> &rhs);

  std::shared_ptr<const Concept> ptr_;

public:
  template<typename T>
  explicit inline Wrapper(T a)
      : ptr_(std::make_shared<Model<A<T>>>(std::move(a))) {}

  template<typename U>
  friend inline void someFriend(Wrapper &lhs, B<U> &rhs) {
    doSomething(*lhs.ptr_, rhs);
  }
};

请注意,我能够static_cast友元函数内的Concept类,因为它的类型可以从Model<T>类的上下文中推断出来。

所以,我可以用这样的代码:

Wrapper a(1);
B<int> b{2};

someFriend(a, b);

其输出:

Hello from A! 1
Hello from B! 2
3

我的问题是,是否有某种不可预见的问题,做事情这样。另外,如果我替换指针举行的对象,应在static_cast还能用吗?

一些初步的测试中,我已经运行表明,这是相当可靠的,但我偶尔也会碰到问题,即调用似乎“专业”周围的第一个对象,然后,如果指针变成一个新的对象不切换。

Here是对代码的链接。

c++ c++11
1个回答
3
投票

您违反ODR(一个定义规则),因此你的代码是形成不良的,没有诊断需要。

特别:

template<typename U>
friend inline void doSomething(const Concept &lhs, const B<U> &rhs);

有这多个定义;其实,还有每一个Model<T>。通过ODR,必须有这样的一个定义。

伊利诺伊州形成,没有诊断需要(IL-NDR)是你可以在C ++标准的土地最糟糕的事情。

您所看到的现象是一些随机的实现被调用,和“大棒”。什么都没有安全正在发生。

© www.soinside.com 2019 - 2024. All rights reserved.