【问题标题】:C++ - Multiple parameter packs for variadic functionC++ - 可变参数函数的多个参数包
【发布时间】:2020-07-30 19:15:02
【问题描述】:

我对 c++ 很陌生,对于我的第一个项目,我正在尝试编写一个 ioc 容器,通过向注册函数添加可变参数来扩展 this blog post 中描述的概念。因此,一个参数包将用于可变参数,另一个用于声明要注册的类型的依赖关系。

读了一点之后,我发现了一些类似于我最终尝试做的事情。函数如下所示:

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;
}

我用iocContainer_.RegisterSingletonClassFactory&lt;boost::asio::io_context, std::tuple&lt;&gt;&gt;(30); 调用它。

然而,这给了我错误“错误:没有用于调用的匹配函数”...当 clang 告诉我“候选模板被忽略:模板参数的显式指定参数无效”未使用'"。

有没有办法做到这一点?错误究竟是什么意思?

谢谢

【问题讨论】:

  • 您的意思是std::tuple 而不是std::tuple&lt;&gt;?不过,我怀疑这里还有其他问题。
  • 哦 std::tuple 而不是 std::tuple 似乎可以解决它,谢谢:)
  • 为什么TDependencies...重复了两次?你指的是GetInstance&lt;TDependencies&gt;()...中的哪个包?
  • @Evg 并没有真正重复。第一个TDependencies 只是命名模板模板参数的参数。它对template&lt;template&lt;typename T, T&gt; typename&gt; void foo(); 之类的东西很有用,但在这种情况下它是多余的。在声明“第二个”之前,它超出了范围。整个template 标头可以写成template &lt;typename T, template&lt;typename...&gt; typename TUnused, typename... TDependencies, typename... TArgs&gt;。函数体中唯一名为TDependencies 的是第二个。
  • 现在我在使用iocContainer_.RegisterSingletonClassFactory&lt;listener::ClearTextListener, std::tuple&lt;boost::asio::io_context&gt;&gt;(boost::asio::ip::tcp::endpoint(address, portNr)); 调用该方法时遇到了同样的错误,这可能是一个类似的修复吗? (我当然希望如此)

标签: c++ c++17 variadic-templates


【解决方案1】:

这个错误到底是什么意思?

这个错误意味着你的电话

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

与模板函数的声明不匹配

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

因为你的模板函数等待

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

  2. 模板模板参数 (TUnused)

和其他模板参数传递时

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

  2. 另一个type模板参数(std::tuple&lt;&gt;

如果您想将std::tuple 作为模板模板参数传递,则必须不带模板参数(std::tuple,而不是std::tuple&lt;&gt;)。

鉴于您的 TUnused 参数是...好吧,未使用,...我想您的意图是将其用作类型容器。

但没有必要。

不确定,但在我看来,您正在寻找类似的东西

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

因此您可以显式地列出T 和(可能为空的)TDependecies... 类型列表。

TArgs... 列表是从参数推导出来的

以下是一个愚蠢但正在编译的 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);   
 }

其中Tstd::string(第一个显式模板参数),TDependencies...short, int, long, long long(以下显式模板参数)并且TArgs...int, long, long long(从0, 1l, 2ll 参数推导出来) .

注意您不需要TUnused 模板参数。

【讨论】:

    【解决方案2】:

    现在很清楚,原始问题中并不真正需要std::tuple,但为了完整起见,让我举一个例子说明如何从std::tuple-like 类型中提取Dependencies1支持>。我们所需要的只是额外的间接层级:

    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...);
    }
    

    现在

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

    将调用RegisterSingletonClassFactoryImpl()Dependencies 包为A, B, C


    1 任何其他类型列表

    template<class...>
    class type_list;
    

    可以用来代替std::tuple

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 2019-05-19
      • 1970-01-01
      • 2019-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多