【发布时间】:2016-04-29 01:46:23
【问题描述】:
我正在编写一个工厂,用于使用基类的名称生成子类的实例,并将这个(模板化)工厂与我的类 Foo 一起使用。没关系整个代码,但本质上,工厂有一个从字符串到创建实例的函数的映射;模板参数控制这些函数采用哪些参数。在我的例子中,Foo 的 ctor 和 foo 的任何子类都采用 const Bar&,这就是 ctor 参数的可变参数模板所包含的内容。
我有:
template<typename SubclassKey, typename T, typename... ConstructionArgs>
class Factory {
public:
using Instantiator = T* (*)(ConstructionArgs&&...);
private:
template<typename U>
static T* createInstance(ConstructionArgs&&... args)
{
return new U(std::forward<ConstructionArgs>(args)...);
}
using Instantiators = std::unordered_map<SubclassKey,Instantiator>;
Instantiators subclassInstantiators;
public:
template<typename U>
void registerSubclass(const SubclassKey& subclass_id)
{
static_assert(std::is_base_of<T, U>::value,
"This factory cannot register a class which is is not actually "
"derived from the factory's associated class");
auto it = subclassInstantiators.find(subclass_id);
if (it != subclassInstantiators.end()) {
throw std::logic_error("Repeat registration of the same subclass in this factory.");
}
subclassInstantiators.emplace(subclass_id, &createInstance<U>);
}
};
根据大众的需求,这里还有……
class Foo {
using FooFactory = Factory<std::string, Foo, const Bar&>;
private:
static FooFactory& getTestFactory() {
static FooFactory kernel_test_factory;
return kernel_test_factory;
}
//...
public:
//...
template <typename U>
static void registerInFactory(const std::string& name_of_u) {
Foo::getTestFactory().registerSubclass<U>(name_of_u);
}
Bar bar;
Foo(const Bar& bar_) : bar(bar_) { };
virtual ~Foo() {}
// ...
};
class NiceFoo : public Foo {
// no ctors and dtors
};
不幸的是,由于某种原因,当我打电话时
我收到关于 ctor 期望 const Bar& 的投诉,而我应该在 createInstance 中提供的参数列表实际上是 const Bar。
问题:
- 为什么引用“消失”了?
- 我做错了吗?我应该以不同的方式处理这个问题吗?
GCC 错误输出:
/home/joeuser/myproj/../util/Factory.h(36): error: no instance of constructor "NiceFoo::NiceFoo" matches the argument list
argument types are: (const Bar)
detected during:
instantiation of "T *util::Factory<SubclassKey, T, ConstructionArgs...>::createInstance<U>(ConstructionArgs &&...) [with SubclassKey=std::string, T=Foo, ConstructionArgs=<const Bar &>, U=NiceFoo]"
(59): here
instantiation of "void util::Factory<SubclassKey, T, ConstructionArgs...>::registerSubclass<U>(const SubclassKey &) [with SubclassKey=std::string, T=Foo, ConstructionArgs=<const Bar &>, U=NiceFoo]"
/home/joeuser/myproj/../Foo.h(79): here
instantiation of "void Foo::registerInFactory<U>(const std::string &) [with U=NiceFoo]"
/home/joeuser/myproj/NiceFoo.cpp(122): here
【问题讨论】:
-
请发帖minimal reproducible example。
createInstance是班级成员吗?类模板成员?ConstructionArgs是类模板模板参数吗?函数模板模板参数?NiceFoo期待什么?等等。 -
@Angew:问题是,一个完整的例子不会很少。但我会提出整个工厂课程。为了回答你的问题,
ConstructionArgs是一个可变参数模板参数,NiceFooctor 需要一个const Bar&就像所有Foos -
顺便说一句,MCVE 现在缺少的只是
Foo、NiceFoo和呼叫站点的(简单)定义。没有那么多代码。 (我假设您在一些地方也遗漏了template <class U>)。 -
您的
NiceFoo中需要一个using Foo::Foo;。 -
@einpoklum 这说明了为什么发布 MCVE 很重要:有时,错误出乎意料。
标签: templates c++11 factory variadic-templates perfect-forwarding