最近很多小伙伴都在问将模板化参数包存储在std::function对象和模板参数可以作为数据成员的类型这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展c–boost::functi
最近很多小伙伴都在问将模板化参数包存储在std :: function对象和模板参数可以作为数据成员的类型这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展c – boost :: function如何支持具有不同长度模板参数的模板类、c – std :: async可以调用std :: function对象吗?、c – std :: bind to std :: function?、c – std :: function typedef中的参数名称等相关知识,下面开始了哦!
本文目录一览:- 将模板化参数包存储在std :: function对象(模板参数可以作为数据成员的类型)
- c – boost :: function如何支持具有不同长度模板参数的模板类
- c – std :: async可以调用std :: function对象吗?
- c – std :: bind to std :: function?
- c – std :: function typedef中的参数名称
将模板化参数包存储在std :: function对象(模板参数可以作为数据成员的类型)
您无法使用虚拟模板方法,这主要是您想要在std::function
之后进行类型擦除的方法。
在控制您的库时,您会知道真正使用的每个原型,因此您可以创建一个符合您需求的记录器界面:
struct ILogger
{
virtual ~ILogger() = default;
virtual void write(severity_t,const std::string&) = 0;
virtual void write(severity_t,const std::string&,int) = 0;
virtual void write(severity_t,int,float) = 0;
// ...
};
void set_logger(ILogger&); // custom point
然后提供一种方法,可以从可变参函数轻松创建类,例如:
template <typename Functor>
struct LoggerT : ILogger,Functor
{
using Functor::Functor;
using Functor::operator();
void write(severity_t level,const std::string& format) override { (*this)(level,format);}
void write(severity_t level,const std::string& format,int v1) override { (*this)(level,format,v1);}
void write(severity_t level,int v1,const std::string& v2) override { (*this)(level,v1,v2);}
void write(severity_t level,float v1) override { (*this)(level,v1);}
// ...
};
template <typename Func>
LoggerT<Func> make_logger(Func func) { return {func}; }
然后您的客户只需要写:
struct SpdLogger {
template <typename ... Ts>
void operator () (severity_t level,const std::string& msg,Ts&& args...)
{
if (level == severity_t::warn)
{
spdlog::warn(msg,std::forward<Ts>(args)...);
}
}
};
int main()
{
LoggerT<SpdLogger> logger;
set_logger(logger);
// ...
}
以及在具有常规lambda的C ++ 14中:
auto logger = make_logger([](severity_t level,auto&& args...)
{
if(level == severity_t::warn)
{
spdlog::warn(msg,decltype(args)(args)...); // decltype(args) is the forward
}
});
set_logger(logger);
c – boost :: function如何支持具有不同长度模板参数的模板类
#if !BOOST_PP_IS_ITErating #ifndef D_EXAMPLE_H #define D_EXAMPLE_H #include <boost/function> #include <boost/preprocessor/iteration/iterate.hpp> #define BOOST_PP_IteraTION_ParaMS_1 (3,(1,2,"example.h")) #include BOOST_PP_IteraTE() #else template<class T,BOOST_PP_ENUM_ParaMS(BOOST_PP_IteraTION(),class T)> class Example { boost::function<T,(BOOST_PP_ENUM_ParaMS(BOOST_PP_IteraTION(),T))> func; }; #endif
上面的代码显然不会起作用,因为它在同一个头文件中声明了具有不同模板变量长度的同一个类.我想要实现的是包含一个文件并定义具有不同模板变量长度的类,就像boost :: function一样.
#include "example.h" Example<int,int,float> example1; Example<double,int> example2;
我查了一下boost :: function的代码,但我无法弄清楚它是如何工作的.有任何想法吗?
解决方法
#include <iostream> template<class A,class B = void,class C = void> class Example { public: static const int x = 3; }; template<class A,class B> class Example<A,B,void> { public: static const int x = 2; }; template<class A> class Example<A,void,void> { public: static const int x = 1; }; int main() { Example<int,int> e3; Example<int,int> e2; Example<int> e1; std::cout << e3.x << e2.x << e1.x << std::endl; }
c – std :: async可以调用std :: function对象吗?
#include <iostream> #include <future> #include <functional> using namespace std; class Adder { public: int add(int x,int y) { return x + y; } }; int main(int argc,const char * argv[]) { Adder a; function<int(int,int)> sumFunc = bind(&Adder::add,&a,1,2); auto future = async(launch::async,sumFunc); // ERROR HERE cout << future.get(); return 0; }
错误是:
没有用于调用’async’的匹配函数:
候选模板被忽略:替换失败[使用Fp = std :: _ 1 :: function&,Args =<>]:’std :: _ 1 :: __ invoke_of,>中没有名为’type’的类型
是不是可以与std :: function对象使用异步,或者我做错了什么?
(这是使用Xcode 5和Apple LLVM 5.0编译器编译的)
解决方法
Is it possible to call function objects created with
std::bind
usingstd::async
是的,只要您提供正确数量的参数,就可以调用任何仿函数.
am I doing something wrong?
您将绑定函数(不带参数)转换为函数< int(int,int)>,它接受(并忽略)两个参数;然后尝试在没有参数的情况下启动它.
您可以指定正确的签名:
function<int()> sumFunc = bind(&Adder::add,2);
或者避免创建函数的开销:
auto sumFunc = bind(&Adder::add,2);
或根本不打扰绑定:
auto future = async(launch::async,&Adder::add,2);
或者使用lambda:
auto future = async(launch::async,[]{return a.add(1,2);});
c – std :: bind to std :: function?
std::vector<std::function<int(int)>> functions; std::function<int(int,int)> foo = [](int a,int b){}; std::function<int(int)> bar = std::bind(foo,2); functions.push_back(bar);
我得到的错误是:
/usr/include/c++/4.6/functional:1764:40: error: no match for call to '(std::_Bind<std::function<int(int,int)>(int)>) (int)'
有人可以告诉我如何将std :: bind转换成std ::函数?
解决方法
std::function<int(int)> bar = std::bind(foo,2,std::placeholders::_1);
c – std :: function typedef中的参数名称
std::function
:
typedef std::function<void (const std::string&)> TextChangedHandler
是否允许在typedef中指定参数名称,以使其更加自我记录?例如:
typedef std::function<void (const std::string& text)> TextChangedHandler
我可以添加参数名称,它在Visual C 2010上编译得很好,但我想确保它符合C 03 / C 11标准.
解决方法
这种指定函数类型而没有声明符来命名函数的形式在语法上是一个type-id(8.1):
type-id: type-specifier-seq abstract-declarator[opt] abstract-declarator: ptr-operator abstract-declarator[opt] direct-abstract-declarator direct-abstract-declarator: direct-abstract-declarator[opt] ( parameter-declaration-clause ) cv-qualifier-seq exception-specification direct-abstract-declarator[opt] [ constant-expression ] ( abstract-declarator )
parameter-declaration-clause语法与普通函数声明中的语法相同,它允许每个参数具有名称(声明符)或不具有(抽象声明符)(8.3.5):
parameter-declaration-clause: parameter-declaration-list[opt] ...[opt] parameter-declaration-list[opt],... parameter-declaration-list: parameter-declaration parameter-declaration-list,parameter-declaration parameter-declaration: decl-specifier-seq declarator decl-specifier-seq declarator = assignment-expression decl-specifier-seq abstract-declarator[opt] decl-specifier-seq abstract-declarator[opt] = assignment-expression
关于将模板化参数包存储在std :: function对象和模板参数可以作为数据成员的类型的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于c – boost :: function如何支持具有不同长度模板参数的模板类、c – std :: async可以调用std :: function对象吗?、c – std :: bind to std :: function?、c – std :: function typedef中的参数名称等相关内容,可以在本站寻找。
本文标签: