如何编写工厂函数来初始化C ++中的constexpr引用?

时间:2018-02-10 12:03:57

标签: c++ c++11 constexpr

我想通过工厂函数初始化constexpr引用,但是我没能成功。

#include <stdio.h>
using namespace std;

struct IWorker // common interface of workers
{ virtual void foo() const = 0;
};

template <typename T> // example worker
struct Worker : IWorker
{ T& Target;
  const T Source;
  constexpr Worker(T& target, const T& source) : Target(target), Source(source) {}
  virtual void foo() const { puts("Worker::foo"); Target = Source; }
};

template <typename T> // factory for Worker (and maybe others)
constexpr const Worker<T>& factory(T& target, const T& source)
{ return Worker<T>(target, source);
}

struct R // allow array of references
{ const IWorker& ref;
};

int iVal = 0;

constexpr R table[] 
{ { Worker<int>(iVal, 7) } // works
//, { factory(iVal, 8) } // does not work
};

int main()
{ printf("iVal = %i\n", iVal); // iVal = 0
  table[0].ref.foo();
  printf("iVal = %i\n", iVal); // iVal = 7
  return 0;
}

好的,我可以直接调用所有构造函数,但我更喜欢工厂,因为

  1. 我不需要反复重复类型参数和
  2. 工厂也可以根据参数列表(重载)或参数的constexpr属性选择合适的工人类。
  3. 问题可能与静态引用所需的静态存储有关。

    是否不可能为此目的编写工厂?

    • 如果是,为什么?
    • 如果不是,如何正确实施?

    预期的用例是大型解析器调度表,当然还有更复杂的类。 语言标准是C ++ 11。尽管如此,知道C ++ 17是否可以提供帮助仍然是一件好事,尽管它尚未得到广泛支持。

1 个答案:

答案 0 :(得分:0)

只需在R中使用r值引用,让工厂返回Worker<T>,以便它可以绑定到r值引用

#include <stdio.h>
using namespace std;

struct IWorker // common interface of workers
{
  virtual void foo() const = 0;
};

template <typename T> // example worker
struct Worker : IWorker {
  T &Target;
  const T Source;
  constexpr Worker(T &target, const T &source)
      : Target(target), Source(source) {}
  virtual void foo() const {
    puts("Worker::foo");
    Target = Source;
  }
};

template <typename T> // factory for Worker (and maybe others)
constexpr Worker<T> factory(T &target, const T &source) {
  return Worker<T>(target, source);
}

struct R // allow array of references
{
  IWorker &&ref;
};

int iVal = 0;

constexpr R table[]{
    {Worker<int>(iVal, 7)} // works
    , { factory(iVal, 8) } // does not work
};

int main() {
  printf("iVal = %i\n", iVal); // iVal = 0
  table[0].ref.foo();
  printf("iVal = %i\n", iVal); // iVal = 7
  table[1].ref.foo();
  printf("iVal = %i\n", iVal); // iVal = 8
  return 0;
}