Variadic template templates and perfect forwarding

◇◆丶佛笑我妖孽 提交于 2019-12-17 21:45:53

问题


This question on the object generator pattern got me thinking about ways to automate it.

Essentially, I want to automate the creation of functions like std::make_pair, std::bind1st and std::mem_fun so that instead of having to write a different function for each template class type, you could write a single variadic template template function that handles all cases at once. Usage of this function would be like:

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

Is it possible to write this function make? I have tried this, but it doesn't work in GCC 4.5 or 4.6:

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

If I try to call (e.g) make<std::pair>(1, 2) I just get

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

Have I got the syntax wrong anywhere here?
Or is this right and GCC is wrong?
Or is this just fundamentally impossible in C++0x?

[edit]

Proposal N2555 seems to suggest that this is allowed and GCC claims to have implemented it in GCC4.4.


回答1:


That's exactly right. I would expect it to work. So I think that GCC is in error with rejecting that. 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]$



回答2:


This is probably a GCC quirk. I can get the following to work with a dev snapshot (I don't have a copy of 4.6 right now):

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 */ }



回答3:


This is quite wrong- take make_shared, for example. The point of make_shared is that there are run-time efficiency savings for using it. But what would happen if I tried to use make<std::shared_ptr>? Don't think that would quite work out. Or how about types where only some of the constructor arguments are template arguments, and the rest aren't? For example, make<std::vector, int>(other_vector.begin(), other_vector.end()); - the types of the iterators don't participate, but you pass them in anyway.

It's impossible to write a generic make function.

As for the Standard, well, it could easily have been removed since then. You'd have to check the FDIS.



来源:https://stackoverflow.com/questions/6486432/variadic-template-templates-and-perfect-forwarding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!