您好我正在玩TMP并且正在考虑创建课程 看起来像是:
template<typename T, typename LogFunc>
class
{
(其中LogFunc应默认为“nop”函数)
想法是让一个类为T类实例定义一些功能,例如检查数字是否为偶数,还可以选择通过调用
来记录void memberFunc(T& t)
{
LogFunc(t);
}
或者
void memberFunc(T& t)
{
LogFunc lf;
lf(t);
}
可以吗? 从阅读A on SO,lambdas有点像templ params一样有问题。 顺便说一句,如果有人关心this是我尝试的但是打印出来
:(
答案 0 :(得分:3)
问题是lambda的类型是编译器强制的单例;它只有一个值,就是lambda本身;此外,该类型具有已删除的构造函数。因此,即使使用decltype,您也无法将lambdas作为模板实例化的一部分传递。但是没有什么可以阻止你将它们作为构造函数参数传递。
但是,这里我们遇到另一个问题:构造函数参数不用于推导模板实例化(这就是标准库提供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);
}
答案 1 :(得分:2)
这不会直接回答,但会提供一些关于你做了什么的提示。
LogFunc
参数是一种类型(不是对象),因此
LogFunc(t)
创建一个临时LogFunc
,将t
作为参数(您实际上是在调用LogFunc::LogFunc(T&)
构造函数)。LogFunc lf; lf(t);
创建一个堆栈生活默认构造Logfunc
,名为lf,lf(t)
调用其LogFunc::operator()(T&)
成员函数。LogFunc()(t)
创建一个临时默认构造的LogFUnc,并在其上调用operator()(T&amp;)。关于lambdas,它们实际上是构造函数获取捕获的变量的类,其operator()接受您声明的参数。但它们只存在于编译器的“内部”,并且没有可以引用的“名称”。
您可以做的是使用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;
}
编译为“g ++ -pedantic -Wall -std = c ++ 11”,并将ouptut
5
答案 2 :(得分:1)
其他答案都很好,但您也可以使用std::function<T>
传递构造函数参数。看起来像这样:
#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);
}
#include <iostream>
template <typename T> struct OtherC{
void operator()(T v){ std::cout <<"other "<<v<<std::endl; };
};
template <typename T> struct NoopC{
void operator()(T){ std::cout << "noop"<<std::endl; };
};
template<typename T, template <typename X> class F = NoopC >
struct A{
static void memberFunc(T valx){ F<T>()(valx); }
};
int main(){
A<int> aNoop;
A<float,OtherC> aSomeOther ;
aNoop.memberFunc(5);
aSomeOther.memberFunc(3.55);
}