56

这个关于对象生成器模式的问题让我想到了自动化它的方法。

本质上,我想自动创建像std::make_pair,这样的函数std::bind1ststd::mem_fun这样就不必为每个模板类类型编写不同的函数,您可以编写一个单一的可变参数模板模板函数来一次处理所有情况。此功能的用法如下:

make<std::pair>(1, 2);         // equivalent to std::make_pair(1, 2)
make<std::binder2nd>(&foo, 3); // equivalent to std::bind2nd(&foo, 3);

可以写这个函数make吗?我已经尝试过了,但它在 GCC 4.5 或 4.6 中不起作用:

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}

如果我尝试打电话(例如)make<std::pair>(1, 2)我会得到

error: no matching function for call to 'make(int, int)'

我在这里的任何地方都有语法错误吗?
或者这是对的,而 GCC 是错的?
或者这在 C++0x 中根本不可能?

[编辑]

提案N2555似乎表明这是允许的,并且GCC 声称已在 GCC4.4 中实现了它

4

3 回答 3

49

这是完全正确的。我希望它能够工作。所以我认为 GCC 拒绝这一点是错误的。FWIW:

#include <utility>

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}

int main() {
  make<std::pair>(1, 2);
}


// [js@HOST2 cpp]$ clang++ -std=c++0x main1.cpp
// [js@HOST2 cpp]$
于 2011-06-26T20:45:35.917 回答
7

这可能是 GCC 的怪癖。我可以获得以下内容以使用开发快照(我现在没有 4.6 的副本):

template<
    template<typename...> class TemplateClass
    , typename... Args

    , typename Result = TemplateClass<Args...>
    // Also works with the arguably more correct
    // , typename Result = TemplateClass<
    //     typename std::decay<Args>::type...
    // >
>
Result
make(Args&&... args)
{ /* as before */ }
于 2011-06-26T20:45:36.933 回答
4

例如,这是非常错误make_shared的。关键make_shared是使用它可以节省运行时效率。但是如果我尝试使用会发生什么make<std::shared_ptr>?不要认为那会很成功。或者只有一些构造函数参数是模板参数而其余不是模板参数的类型呢?例如,make<std::vector, int>(other_vector.begin(), other_vector.end());- 迭代器的类型不参与,但无论如何你都会传递它们。

make编写通用函数是不可能的。

至于标准,好吧,从那时起它很容易被删除。您必须检查 FDIS。

于 2011-06-26T20:25:25.617 回答