【发布时间】:2019-01-18 08:15:54
【问题描述】:
我正在尝试使用可变参数模板编写一个通用 obj 工厂来调用各种类的构造函数。代码如下:
#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <unordered_map>
template<typename T>
class ObjFactory {
public:
typedef std::shared_ptr<T> ObjPtr;
typedef std::function<ObjPtr(void)> CreatorFunc;
public:
void registerCreator(const std::string &name, const CreatorFunc &creator)
{ m_dictCreator[name] = creator; }
ObjPtr getObj(const std::string &name) const
{
auto it = m_dictCreator.find(name);
return (it == m_dictCreator.end() ? nullptr : (it->second)());
}
private:
std::unordered_map<std::string, CreatorFunc> m_dictCreator;
};
using namespace std;
struct Base {
virtual ~Base() {}
virtual void greet() const
{ cout << "I am Base" << endl; }
};
struct Derived : Base {
Derived() : x(0), y(0) {}
Derived(int a, int b) : x(a), y(b) {}
int x, y;
virtual void greet() const
{ cout << "I am Derived x = " << x << " y = " << y << endl; }
};
template<typename T, typename... Args>
std::shared_ptr<T> create_obj(Args... args) // This OK
// std::shared_ptr<T> create_obj(Args&&... args) // WRONG
{ return std::make_shared<T>(std::forward<Args>(args)...); }
int main()
{
ObjFactory<Base> factory;
factory.registerCreator("default", create_obj<Derived>);
factory.registerCreator("withArgs", std::bind(create_obj<Derived, int, int>, 1, 2));
do {
auto pObj = factory.getObj("default1");
if (pObj) { pObj->greet(); }
} while (0);
do {
auto pObj = factory.getObj("withArgs");
if (pObj) { pObj->greet(); }
} while (0);
return 0;
}
在大多数示例中,可变参数 arg 在函数 arg 列表中总是这样写“Args&&...”。但这不适用于绑定,像这样编译错误消息(clang-902.0.39.2)
错误:从 '__bind 没有可行的转换 (&)(int &&, 整数 &&), int, int>' to 'const ObjFactory::CreatorFunc' (又名'const function ()>') factory.registerCreator("withArgs", std::bind(create_obj, 1, 2));
去掉“&&”后就可以了
但我不知道为什么?
【问题讨论】:
-
这不能解释为什么,但是用 lambda 替换
std::bind(通常是推荐的)按预期工作。[](){ return create_obj<Derived>(1,2); } -
如果有兴趣,OPs 问题的最小案例can be found here。
-
std::bind在你没有 C++11 时进行降神会,否则你应该使用 lambda。
标签: c++ variadic-templates stdbind