我试图编写一个通用的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总是这样写“Args”
错误:没有可行的转换从'__bind(
在移除“
但我不知道为什么?
当使用转发引用时,您需要让参数被推断出来,否则您无法完美地转发它们,因为您不知道用于它们的真正类型。
在您的案例中,您给出了一个类型create\u obj
您将可调用项分配给一个
常量CreatorFunc
替换
create_obj
真正的解决方案是使用lambda。
通用参考仅在推导的上下文中起作用。当显式指定模板参数时,它们不会像您期望的那样工作。
给定函数模板
template <typename... Args>
void foo(Args&&... args) {}
还有那个电话
int a = 1;
int b = 2;
foo(a, b);
Args
将被推断为{int
如果使用参数的右值调用它(即
foo(1,2)
),则Args
将被推断为{int,int}
,并且Args
中的值类型将变为{int>
这是通用引用的基础,现在让我们看看当你调用时会发生什么
auto fn = std::bind(foo<int, int>, 1, 2);
fn();
这里,您不允许进行模板参数推断,因此
Args
是{int,int}
,因此foo
需要{int>类型的参数
正确执行此操作的方法是使用lambda而不是
std::bind
:
auto fn = []() { foo(1, 2); };
fn();
使用lambda时,模板参数推断工作正常,
1
和2
保持右值。一切都按预期进行,通用引用也发挥了作用,因为它们是在推导的上下文中使用的。
我有两个变量类成员函数。当第一个被调用时,我想创建一个std::function到第二个类成员函数,然后将的参数绑定到函数指针。 所以稍后我可以调用,而不必将所有参数传递给 我想避免使它成为模板类,并将参数存储在元组中。 我试图让以下示例起作用: 链接到live示例:http://cpp.sh/4ylm 当我编译时,我得到一个错误 模板参数推断/替换失败:17:37: 注意:无法推断模板参数“\u
多亏了C11,我们收到了系列的仿函数包装器。不幸的是,我一直只听到关于这些新添加的不好的消息。最受欢迎的是它们非常慢。我测试了它,与模板相比,它们真的很糟糕。 111毫秒对1241毫秒。我认为这是因为模板可以很好地内联,而通过虚拟调用覆盖内部。 显然,在我看来,模板也有其问题: 它们必须以头的形式提供,这不是您在以封闭代码形式发布库时可能不希望做的事情, 因此,我可以假设s可以用作传递函子的事实标
在C++11之前,类模板和函数模板只能含有固定数量的模板参数。C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。可变参数模板的加入使得C++11的功能变得更加强大,而由此也带来了许多神奇的用法。 可变参数模板 可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面带上省略号...: template<ty
我发现了和类型推导的以下行为,这对我来说是意想不到的: 中的两行都会导致错误: 没有函数模板“stdfunc_test”的实例与参数列表匹配 尝试在Visual Studio 2015中编译时。 为什么类型演绎不从函数类型中演绎模板类型,有没有变通方法?
我目前有一个,但是为了灵活性,我希望能够分配一个lambda表达式,将作为映射中的值返回。 所以我创建了这个模板类: 并像这样使用它: IntelliSense提供了更多信息: 多个操作符“=”匹配这些操作数:function“valueorfunction::operator=(const std::function&other)[with T=std::wstring]”function“va
我试图理解下面代码中的编译器错误。我有一个variadic模板函数,它接受具有指定类型的lambda,试图调用该函数会导致模板由于不匹配而不被视为有效的候选模板。 如果我将声明更改为不变: 然后它为上面的玩具示例工作,但对于真正的问题,我需要任意的论点。我是不是缺少了什么,或者还有什么方法可以做到这一点? 编辑:这被错误地标记为重复,我相信--受骗者没有回答我所问的问题。这个问题特别与这里的var