简体   繁体   English

C++ - 可变参数 function 的多个参数包

[英]C++ - Multiple parameter packs for variadic function

I am pretty new to c++ and for my first project am trying to write an ioc container expanding the concept described in this blog post by adding variadic arguments to the registering functions.我对 c++ 很陌生,对于我的第一个项目,我正在尝试编写一个 ioc 容器,通过将可变参数 arguments 添加到注册函数来扩展此博客文章中描述的概念。 So one parameter pack would be used for variadic arguments and the other one to declare the dependencies of the type to register.因此,一个参数包将用于可变参数 arguments,另一个用于声明要注册的类型的依赖关系。

After reading a bit I came across stuff similar to what I tried to do in the end.在阅读了一点之后,我遇到了类似于我最终尝试做的事情。 The function looks like this: function 看起来像这样:

template <class T,
        template<typename ...TDependencies> typename TUnused, typename... TDependencies,
        typename ...TArgs>
void RegisterSingletonClassFactory(TArgs...args)
{
    std::string typeKey = typeid(T).name();
    creatorMap_[typeKey] = [this, args...](){
        return new T(GetInstance<TDependencies>()..., args...);
    };

    std::shared_ptr<IHolder> iHolder = instanceMap_[typeKey];
    auto * holder = dynamic_cast<Holder<T>*>(iHolder.get());
    if(holder != nullptr)
        holder->instance_ = nullptr;
}

And I call it with iocContainer_.RegisterSingletonClassFactory<boost::asio::io_context, std::tuple<>>(30);我用iocContainer_.RegisterSingletonClassFactory<boost::asio::io_context, std::tuple<>>(30);调用它. .

This however gives me the error " error: no matching function for call to "... with clang telling me " candidate template ignored: invalid explicitly-specified argument for template parameter 'TUnused' ".然而,这给了我错误“错误:没有匹配的 function 调用“...... clang 告诉我“候选模板被忽略:模板参数'TUnused'的无效显式指定参数”。

Is there a way to do this?有没有办法做到这一点? And what exactly does the error mean?错误究竟是什么意思?

Thanks谢谢

And what exactly does the error mean?错误究竟是什么意思?

The error mean that your call该错误意味着您的电话

iocContainer_.RegisterSingletonClassFactory<boost::asio::io_context, std::tuple<>>(30);

doesn't matches the declaration of your template function与您的模板 function 的声明不匹配

template <class T,
        template<typename ...TDependencies> typename TUnused, typename... TDependencies,
        typename ...TArgs>
void RegisterSingletonClassFactory(TArgs...args)

because your template functions waits for因为您的模板函数等待

  1. a type parameter ( T ),一个类型参数( T ),

  2. a template-template parameter ( TUnused )模板模板参数( TUnused

and other template parameters when you pass和其他模板参数传递时

  1. a type paramer ( boost::asio::io_context )类型参数( boost::asio::io_context

  2. another type template parameter ( std::tuple<> )另一种类型模板参数( std::tuple<>

If you want to pass std::tuple as template-template parameter, you have to pass it without template parameters ( std::tuple , not std::tuple<> ).如果要将std::tuple作为模板模板参数传递,则必须在没有模板参数的情况下传递它( std::tuple ,而不是std::tuple<> )。

Given that your TUnused parameter is... well, unused,... I suppose that your intention was to use it as type container.鉴于您的TUnused参数是......好吧,未使用,......我想你的意图是将它用作类型容器。

But there is no needs for it.但是没有必要。

Not sure but seems to me that your looking for something similar不确定,但在我看来,您正在寻找类似的东西

template <typename T, typename... TDependencies, typename ...TArgs>
void foo (TArgs...args)

So you can explicit T and a (maybe empty) TDependecies... list of types.所以你可以显式的T和一个(可能是空的) TDependecies...类型列表。

The TArgs... list is deduced from the arguments TArgs...列表是从 arguments 推导出来的

The following is a silly, but compiling, C++17 example下面是一个傻,但是编译,C++17例子

#include <iostream>

template <typename T, typename... TDependencies, typename ...TArgs>
void foo (TArgs...args)
 {
   std::cout << "T:" << typeid(T).name() << std::endl;

   std::cout << "TDependecies list:" << std::endl;

   ((std::cout << "- " << typeid(TDependencies).name() << std::endl), ...);

   std::cout << "TArgs list:" << std::endl;

   ((std::cout << "- " << typeid(TArgs).name() << std::endl), ...);
 }

int main()
 {
   foo<std::string, short, int, long, long long>(0, 1l, 2ll);   
 }

where T is std::string (the first explicit template parameters), TDependencies... is short, int, long, long long (the following explicit template parameters) and TArgs... is int, long, long long (deduced from the 0, 1l, 2ll arguments).其中Tstd::string (第一个显式模板参数), TDependencies...short, int, long, long long (以下显式模板参数)和TArgs...int, long, long long (推导自0, 1l, 2ll参数)。

Observe that you don't need the TUnused template parameter.请注意,您不需要TUnused模板参数。

It is clear now that std::tuple was not really needed in the original problem, but for completeness let me give an example of how Dependencies could be extracted from the std::tuple -like types 1 .现在很清楚,原始问题中并不真正需要std::tuple ,但为了完整起见,让我举一个例子来说明如何从std::tuple类类型1中提取Dependencies项。 All we need is an additional level of indirection:我们需要的只是一个额外的间接级别:

template<class T>
struct wrapper {};

template<class T, template<class...> class Unused, 
         class... Dependencies, class... Args>
void RegisterSingletonClassFactoryImpl(
    wrapper<Unused<Dependencies...>>, Args... args) {

    std::string typeKey = typeid(T).name();
    creatorMap_[typeKey] = [this, args...]() {
        return new T(GetInstance<Dependencies>()..., args...);
    }; 
    // ...
}

template<class T, class Unused, class... Args>
void RegisterSingletonClassFactory(Args... args) {
    RegisterSingletonClassFactoryImpl<T>(wrapper<Unused>{}, args...);
}

Now现在

RegisterSingletonClassFactory<T, std::tuple<A, B, C>>()

will call RegisterSingletonClassFactoryImpl() with Dependencies pack being A, B, C .将调用RegisterSingletonClassFactoryImpl()Dependencies包为A, B, C


1 Any other type list 1任何其他类型列表

template<class...>
class type_list;

can be used instead of std::tuple .可以用来代替std::tuple

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM