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

Posted

技术标签:

【中文标题】如何编写工厂函数来初始化 C++ 中的 constexpr 引用?【英文标题】:How to write a factory function to initialize a constexpr reference in C++? 【发布时间】:2018-02-10 12:03:57 【问题描述】:

我想通过一个工厂函数初始化一个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;

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

    我不需要一遍又一遍地重复类型参数 工厂还可以根据参数列表(重载)甚至参数的 constexpr 属性选择适当的工作类。

问题可能与静态引用所需的静态存储有关。

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

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

预期的用例是大型解析器调度表,当然还有更复杂的类。 语言标准是 C++11。不过,最好知道 C++17 是否有帮助,尽管它尚未得到广泛支持。

【问题讨论】:

@Jorge Y. 您的解决方案非常接近:从工厂中删除 const 就可以了。您应该取消删除并更新它。可能是constprevents RVO。 【参考方案1】:

只需在R 中使用右值引用并让您的工厂返回Worker&lt;T&gt;,以便它可以绑定到右值引用

#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;

【讨论】:

r 值参考似乎不是故事的重要部分。工厂的返回类型必须是按值,并且必须是non-const

以上是关于如何编写工厂函数来初始化 C++ 中的 constexpr 引用?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 子类的构造函数中初始化超类的 const 成员变量?

如何验证 C++ 构造函数中的输入参数?

C++类和对象下

C++面向对象-static、const

接受对抽象类的 const 引用的 C++ 构造函数无法初始化 std::map

C++中如何可以修改const函数内的成员变量的值?