指向构造函数重载的指针?
Posted
技术标签:
【中文标题】指向构造函数重载的指针?【英文标题】: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 ..
这样我们就可以从&MakeFooA<FooType1>
、&MakeFooA<FooType2>
等中获取函数指针,而无需任何宏hacky。
但这似乎仍然是不必要的样板 --- 是否有 (C++11) 方法可以将函数指针直接指向“使用带有 A
的构造函数调用 FooType1
的运算符 new
”无需编写所有这些包装函数?
【问题讨论】:
是的,写一个 4 行函数的样板文件太糟糕了……事实上,很多人不需要一个指向返回新分配对象的函数的指针任意类型。有些人会这样做,但您可以自己编写,就像您所做的那样。 @Nicol:实际代码中大概有20个。 C++ 不允许您获取构造函数的地址。因此,您必须将new
包装在一个函数中,然后才能获取该函数的地址。使用模板是最简洁的解决方案,但我建议使用双参数模板,这样您也可以指定 arg
类型名,然后您不需要单独的 A
和 B
函数。 template<typename FooType, typename ArgType> FooType* makeFoo(ArgType arg) return new FooType(arg);
、&MakeFoo<FooType1, A>
、&MakeFoo<FooType1, B>
等
为什么有20行?您可以使用可变参数模板来传递任意数量的参数类型。
你需要这样的指针做什么? makeFoo<X>(a)
解决了写 new X(a)
不能解决的什么问题?
【参考方案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>;
【讨论】:
以上是关于指向构造函数重载的指针?的主要内容,如果未能解决你的问题,请参考以下文章