C++ - 可变参数函数的多个参数包
C++ - Multiple parameter packs for variadic function
我是 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<boost::asio::io_context, std::tuple<>>(30);
来称呼它。
然而,这给了我错误“错误:没有匹配的函数调用”... clang 告诉我“候选模板被忽略:明确无效-为模板参数指定参数 'TUnused'".
有办法吗?错误的确切含义是什么?
谢谢
And what exactly does the error mean?
错误意味着你的电话
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)
因为您的模板函数等待
类型参数(T
),
一个模板-模板参数(TUnused
)
和其他模板参数当你传递
类型参数 (boost::asio::io_context
)
另一个类型模板参数(std::tuple<>
)
如果您想将 std::tuple
作为模板-模板参数传递,则必须在不传递模板参数的情况下传递它(std::tuple
,而不是 std::tuple<>
)。
鉴于您的 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);
}
其中T
是std::string
(第一个显式模板参数),TDependencies...
是short, int, long, long long
(后面的显式模板参数),TArgs...
是int, long, long long
(从 0, 1l, 2ll
参数推导出来)。
注意您不需要 TUnused
模板参数。
现在很清楚 std::tuple
在原始问题中并不是真正需要的,但是为了完整起见,让我举一个例子说明如何从 std::tuple
中提取 Dependencies
-喜欢类型1。我们所需要的只是一个额外的间接级别:
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
。
我是 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<boost::asio::io_context, std::tuple<>>(30);
来称呼它。
然而,这给了我错误“错误:没有匹配的函数调用”... clang 告诉我“候选模板被忽略:明确无效-为模板参数指定参数 'TUnused'".
有办法吗?错误的确切含义是什么?
谢谢
And what exactly does the error mean?
错误意味着你的电话
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)
因为您的模板函数等待
类型参数(
T
),一个模板-模板参数(
TUnused
)
和其他模板参数当你传递
类型参数 (
boost::asio::io_context
)另一个类型模板参数(
std::tuple<>
)
如果您想将 std::tuple
作为模板-模板参数传递,则必须在不传递模板参数的情况下传递它(std::tuple
,而不是 std::tuple<>
)。
鉴于您的 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);
}
其中T
是std::string
(第一个显式模板参数),TDependencies...
是short, int, long, long long
(后面的显式模板参数),TArgs...
是int, long, long long
(从 0, 1l, 2ll
参数推导出来)。
注意您不需要 TUnused
模板参数。
现在很清楚 std::tuple
在原始问题中并不是真正需要的,但是为了完整起见,让我举一个例子说明如何从 std::tuple
中提取 Dependencies
-喜欢类型1。我们所需要的只是一个额外的间接级别:
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
。