C++ 如何将std::function或lambda作为(可选)模板参数?
嗨,我在和TMP玩,正在考虑生成一个类 这看起来像:C++ 如何将std::function或lambda作为(可选)模板参数?,c++,c++11,template-meta-programming,C++,C++11,Template Meta Programming,嗨,我在和TMP玩,正在考虑生成一个类 这看起来像: template<typename T, typename LogFunc> class { 或许 void memberFunc(T& t) { LogFunc lf; lf(t); } 能做到吗? 从上面的阅读来看,lambda与temp参数一样有点问题。 顺便说一句,如果有人在乎我试过的,但它打印出来了 :( 这不会直接回答,但会给出一些关于您所做工作的提示 LogFunc参数是一种类型(不是对象),因此
template<typename T, typename LogFunc>
class
{
或许
void memberFunc(T& t)
{
LogFunc lf;
lf(t);
}
能做到吗?
从上面的阅读来看,lambda与temp参数一样有点问题。
顺便说一句,如果有人在乎我试过的,但它打印出来了
:(
这不会直接回答,但会给出一些关于您所做工作的提示
LogFunc
参数是一种类型(不是对象),因此
创建一个临时的LogFunc(t)
将LogFunc
作为参数(实际上您正在调用t
构造函数)LogFunc::LogFunc(t&)
创建一个名为lf的、由LogFunc-lf;lf(t);
构造的堆栈,并且LogFunc
调用其lf(t)
成员函数LogFunc::operator()(t&)
创建一个临时默认构造的LogFunc,并对其调用操作符()(t&)LogFunc()(t)
decltype
或自由函数推断其类型
通常,参数化函数类存储在构造时初始化的frunction对象
#include <iostream>
template<class Fn>
class LogFunc
{
public:
LogFunc(Fn f) :fn(f) {}
template<class T>
void memberFunc(T& t)
{ fn(t); }
private:
Fn fn;
};
template<class Fn>
LogFunc<Fn> makeLogFunc(Fn f)
{ return LogFunc<Fn>(f); }
int main()
{
int x=5;
auto lf = makeLogFunc([](int& a){ std::cout << a << std::endl; });
lf.memberFunc(x);
return 0;
}
这不会直接回答,但会给出一些关于您所做工作的提示
LogFunc
参数是一种类型(不是对象),因此
创建一个临时的LogFunc(t)
将LogFunc
作为参数(实际上您正在调用t
构造函数)LogFunc::LogFunc(t&)
创建一个名为lf的、由LogFunc-lf;lf(t);
构造的堆栈,并且LogFunc
调用其lf(t)
成员函数LogFunc::operator()(t&)
创建一个临时默认构造的LogFunc,并对其调用操作符()(t&)LogFunc()(t)
decltype
或自由函数推断其类型
通常,参数化函数类存储在构造时初始化的frunction对象
#include <iostream>
template<class Fn>
class LogFunc
{
public:
LogFunc(Fn f) :fn(f) {}
template<class T>
void memberFunc(T& t)
{ fn(t); }
private:
Fn fn;
};
template<class Fn>
LogFunc<Fn> makeLogFunc(Fn f)
{ return LogFunc<Fn>(f); }
int main()
{
int x=5;
auto lf = makeLogFunc([](int& a){ std::cout << a << std::endl; });
lf.memberFunc(x);
return 0;
}
问题是lambda的类型是编译器强制的单例;它只有一个值,即lambda本身;此外,该类型有一个已删除的构造函数。因此,即使使用decltype,也不能将lambda作为模板实例化的一部分传递。但没有什么可以阻止您将其作为构造函数参数传递 但是,这里我们遇到了另一个问题:构造函数参数不用于推断模板实例化(这就是为什么标准库提供了make_pair和make_tuple等实用程序),因此我们需要一个模板化的工厂函数 综上所述,解决方案非常简单:
template<typename T, typename LogFunc>
class Foo {
public:
Foo(const T& t, LogFunc fn) : t_(t), lfn_(fn) {}
//...
private:
T t_;
LogFunc lfn_;
};
struct Noop {
template<typename...A>
void operator()(A...) { };
};
template<typename T, typename LogFunc=Noop>
Foo<T, LogFunc> make_foo(const T& t, LogFunc func=LogFunc()) {
return Foo<T, LogFunc>(t, func);
}
模板
福班{
公众:
Foo(const T&T,LogFunc fn):T(T),lfn(fn){
//...
私人:
T!;
LogFunc-lfn;
};
结构Noop{
模板
void运算符()(A…){};
};
模板
Foo make_Foo(const T&T,LogFunc func=LogFunc()){
返回Foo(t,func);
}
问题在于lambda的类型是编译器强制的单例;它只有一个值,即lambda本身;此外,该类型有一个已删除的构造函数。因此,即使使用decltype,也不能将lambda作为模板实例化的一部分传递。但没有什么可以阻止您将其作为构造函数参数传递
但是,这里我们遇到了另一个问题:构造函数参数不用于推断模板实例化(这就是为什么标准库提供了make_pair和make_tuple等实用程序),因此我们需要一个模板化的工厂函数
综上所述,解决方案非常简单:
template<typename T, typename LogFunc>
class Foo {
public:
Foo(const T& t, LogFunc fn) : t_(t), lfn_(fn) {}
//...
private:
T t_;
LogFunc lfn_;
};
struct Noop {
template<typename...A>
void operator()(A...) { };
};
template<typename T, typename LogFunc=Noop>
Foo<T, LogFunc> make_foo(const T& t, LogFunc func=LogFunc()) {
return Foo<T, LogFunc>(t, func);
}
模板
福班{
公众:
Foo(const T&T,LogFunc fn):T(T),lfn(fn){
//...
私人:
T!;
LogFunc-lfn;
};
结构Noop{
模板
void运算符()(A…){};
};
模板
Foo make_Foo(const T&T,LogFunc func=LogFunc()){
返回Foo(t,func);
}
其他答案都很好,但您也可以使用std::function
传入一个构造函数参数
#include <functional>
#include <iostream>
template <typename T> void someOther(T val){
std::cout << "used other "<<val<<std::endl;
}
template <typename T> void noop(T val){
std::cout << "noop "<<val<<std::endl;
}
template<typename T>
struct A{
A(std::function<void(T)> f =noop<T> ) : mf(f){}
void memberFunc(T valx){
mf(valx);
}
std::function<void(T)> mf;
};
int main(){
A<int> aNoop; ;
A<float> aSomeOther{someOther<float>} ;
aNoop.memberFunc(5);
aSomeOther.memberFunc(3.55);
}
#包括
#包括
其他模板无效(T val){
std::cout其他答案都很好,但是您也可以使用std::function
传入一个构造函数参数
#include <functional>
#include <iostream>
template <typename T> void someOther(T val){
std::cout << "used other "<<val<<std::endl;
}
template <typename T> void noop(T val){
std::cout << "noop "<<val<<std::endl;
}
template<typename T>
struct A{
A(std::function<void(T)> f =noop<T> ) : mf(f){}
void memberFunc(T valx){
mf(valx);
}
std::function<void(T)> mf;
};
int main(){
A<int> aNoop; ;
A<float> aSomeOther{someOther<float>} ;
aNoop.memberFunc(5);
aSomeOther.memberFunc(3.55);
}
#包括
#包括
其他模板无效(T val){
std::cout lambda不是类型,它们不能作为模板参数传递。你真的不能仅仅创建一个no-op结构来用作默认参数吗?它必须是一个运行时多态函子或lambda?struct noop{void operator()(const t&){};
对你来说太多了吗?仅仅因为lambda的存在并不意味着你应该忘记其他的一切。这里有decltype:)尽管idk在这种情况下如何使用它(请参阅链接)@nicolabolas这不仅仅是默认的noop点,而是在我需要时实际指定参数。呃,除非我有误解,否则在粘贴的代码中,你从来没有将log_func
设置为值。你定义了lambdada
,但你只使用它的类型,而不是实际值。你为什么期望code显示除以外的任何内容:(
?lambda不是类型,它们不能作为模板参数传递。你真的不能只创建一个no-op结构用作默认参数?它必须是一个运行时多态函子或lambda?结构noop{void操作符()(const t&){};
是