【问题标题】:Pointer to constructor overload?指向构造函数重载的指针?
【发布时间】:2016-06-15 18:38:38
【问题描述】:

我有一堆看起来像这样的遗留代码:

#define MAKE_FOO_FNS(fooname) \
fooname* makeFoo_ ## fooname ## A(A arg) { \
  return new fooname(arg); \
} \
fooname* makeFoo_ ## fooname ## B(B arg) { \
  return new fooname(arg); \
} \
// ... repeated many more times 

这样在后面的代码中我们可以说:

MAKE_FOO_FNS(FooType1);
MAKE_FOO_FNS(FooType2);

然后可以访问具有以下类型的函数指针:

 FooType1* (*)(A);
 FooType1* (*)(B);
 FooType2* (*)(A);
 FooType2* (*)(B);

我知道我可以用模板替换MAKE_FOO_FNS

template<typename FooType>
FooType* makeFooA(A arg) {
  return new FooType(arg);
}
// .. etc ..

这样我们就可以从&amp;MakeFooA&lt;FooType1&gt;&amp;MakeFooA&lt;FooType2&gt;等中获取函数指针,而无需任何宏hacky。

但这似乎仍然是不必要的样板 --- 是否有 (C++11) 方法可以将函数指针直接指向“使用带有 A 的构造函数调用 FooType1 的运算符 new”无需编写所有这些包装函数?

【问题讨论】:

  • 是的,写一个 4 行函数的样板文件太糟糕了……事实上,很多人不需要一个指向返回新分配对象的函数的指针任意类型。有些人会这样做,但您可以自己编写,就像您所做的那样。
  • @Nicol:实际代码中大概有20个。
  • C++ 不允许您获取构造函数的地址。因此,您必须将new 包装在一个函数中,然后才能获取该函数的地址。使用模板是最简洁的解决方案,但我建议使用双参数模板,这样您也可以指定 arg 类型名,然后您不需要单独的 AB 函数。 template&lt;typename FooType, typename ArgType&gt; FooType* makeFoo(ArgType arg) { return new FooType(arg); }&amp;MakeFoo&lt;FooType1, A&gt;&amp;MakeFoo&lt;FooType1, B&gt;
  • 为什么有20行?您可以使用可变参数模板来传递任意数量的参数类型。
  • 你需要这样的指针做什么? makeFoo&lt;X&gt;(a) 解决了写 new X(a) 不能解决的什么问题?

标签: c++ c++11 function-pointers member-function-pointers


【解决方案1】:

您可以将所有 makeFooA()、makeFooB() 等函数合并到一个通用模板中:

template<typename T, typename... Args>
T* make_ptr(Args&&... args)
{
    return new T(std::forward<Args>(args)...);
}

这样做的优点是现在可以传递多个参数(通过值或通过引用),缺点是在获取地址时需要指定完整签名,即 &make_ptr。

注意,如果你有boost,你不需要自己实现:http://www.boost.org/doc/libs/1_61_0/libs/functional/factory/doc/html/

【讨论】:

    【解决方案2】:

    是的,只需使用 lambda。无捕获的 lambda 可以隐式转换为函数指针:

    X*(*p)(A) = [](A arg){ return new X(arg); };
    

    如果您想要更少的输入和更高的安全性,您也可以将指针指向std::make_unique 的正确特化:

    auto p2 = std::make_unique<X, A>;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 2023-03-22
      • 1970-01-01
      • 2018-06-08
      • 2010-10-31
      • 1970-01-01
      相关资源
      最近更新 更多