问题描述
假设我有一个头 wrapper.h
:
模板< typename Func> void wrapper(const Func func);
和一个文件 wrapper.cpp
包含:
#includewrapper.h
模板< typename Func>
void wrapper(const Func func)
{
func();
}
以及 main.cpp
包含:
#includewrapper.h
#include< iostream>
int main()
{
wrapper([](){std :: cout<<hello。<< std :: endl;}) ;如果我将这些一起编译(例如,
cat wrapper.cpp main.cpp | g ++ -std = c ++ 11 -o main -x c ++ -
),我没有链接器错误。
但是,如果我分别编译它们(例如, g ++ -std = c ++ 11 -o wrapper.o -c wrapper.cpp&& g ++ -std = c ++ 11 -o main main.cpp wrapper.o
),I ---当然---得到一个链接器错误:
架构x86_64的未定义符号:
void wrapper< main :: $ _ 0>(main :: $ _ 0),引用来自:
main在main-5f3a90 .o
通常情况下,我可以显式地专门化 wrapper
并添加如下内容到 wrapper.cpp
:
template void包装< void(*)()>(void(*)())
模板专门化不起作用。
是否可以在lambda上专门化模板?
解决方案首先,我假设你知道
回答您的问题:
不幸的是,模板专业化与确切匹配,并且 lambda
是唯一的未命名类型。问题在于你不知道的那种类型。
最好的办法是使用 std :: function
;或者如你所做的那样,然后通过添加 +
<$ p $来强制将lambda转换为函数指针p> int main()
{
wrapper(+ [](){std :: cout<<hello。<< std :: endl;} );
$ / code>
完整示例:
#include< iostream>
模板< typename Func>
void wrapper(const Func func)
{
std :: cout<< PRIMARY\\\
;
func();
}
模板<>
void wrapper< void(*)()>(void(* func)())
{$ b $ std :: cout<< SPECIALIZATION\\\
;
func();
int main()
{
wrapper([](){std :: cout << std :: endl;});
wrapper(+ [](){std :: cout<<world。<< std :: endl;});
}
这将打印
PRIMARY
hello
SPECIALIZATION
world
另外, decltype
facility不起作用,,它会带走您对lambda
需求的灵活性
Suppose I have a header wrapper.h
:
template <typename Func> void wrapper(const Func func);
and a file wrapper.cpp
containing:
#include "wrapper.h"
template <typename Func>
void wrapper(const Func func)
{
func();
}
And a file main.cpp
containing:
#include "wrapper.h"
#include <iostream>
int main()
{
wrapper( [](){std::cout<<"hello."<<std::endl;} );
}
If I compile these together (e.g., cat wrapper.cpp main.cpp | g++ -std=c++11 -o main -x c++ -
), I get no linker errors.
But if I compile them separately (e.g., g++ -std=c++11 -o wrapper.o -c wrapper.cpp && g++ -std=c++11 -o main main.cpp wrapper.o
), I --- of course --- get a linker error:
Undefined symbols for architecture x86_64:
"void wrapper<main::$_0>(main::$_0)", referenced from:
_main in main-5f3a90.o
Normally, I could explicitly specialize wrapper
and add something like this to wrapper.cpp
:
template void wrapper<void(*)()>(void(*)())
But this particular template specialization doesn't work.
Is it possible to specialize a template on a lambda?
First, I assume you know about Why can templates only be implemented in the header file?
To your question:
Unfortunately No, template specializations work with exact match, and a lambda
is a unique unnamed type. The problem is specializing for that type which you do not know.
Your best bet is to use std::function
; or as you have done, then additionally force the lambda to be converted into a function pointer by adding +
int main()
{
wrapper(+[](){std::cout<<"hello."<<std::endl;} );
}
Full example:
#include <iostream>
template <typename Func>
void wrapper(const Func func)
{
std::cout << "PRIMARY\n";
func();
}
template <>
void wrapper<void(*)()>(void(*func)())
{
std::cout << "SPECIALIZATION\n";
func();
}
int main()
{
wrapper([](){std::cout<<"hello\n"<<std::endl;} );
wrapper(+[](){std::cout<<"world."<<std::endl;} );
}
This will print
PRIMARY
hello
SPECIALIZATION
world
Also, decltype
facility wouldn't help, if it does, it will take away the flexibility of your need for lambda
这篇关于是否有可能明确专门化模板来匹配lambda?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!