是否可以显式专门化模板来匹配lambda?

Ale*_*son 5 c++ lambda gcc templates c++11

假设我有一个标题wrapper.h:

template <typename Func> void wrapper(const Func func);
Run Code Online (Sandbox Code Playgroud)

和一个文件wrapper.cpp包含:

#include "wrapper.h"
template <typename Func>
void wrapper(const Func  func)
{
  func();
}
Run Code Online (Sandbox Code Playgroud)

并且文件main.cpp包含:

#include "wrapper.h"
#include <iostream>

int main()
{
  wrapper( [](){std::cout<<"hello."<<std::endl;} );
}
Run Code Online (Sandbox Code Playgroud)

如果我一起编译这些(例如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),我当然---得到一个链接器错误:

Undefined symbols for architecture x86_64:
  "void wrapper<main::$_0>(main::$_0)", referenced from:
      _main in main-5f3a90.o
Run Code Online (Sandbox Code Playgroud)

通常,我可以明确地专门化wrapper并添加这样的东西wrapper.cpp:

template void wrapper<void(*)()>(void(*)())
Run Code Online (Sandbox Code Playgroud)

但是这种特殊的模板专业化不起作用.

是否可以在lambda上专门化模板?

Whi*_*TiM 9

首先,我假设你知道为什么模板只能在头文件中实现?

对于你的问题:

是否可以在lambda上专门化模板?

不幸的是,模板专业化与精确匹配一起使用,而a lambda是一种唯一的未命名类型.问题是专门针对您不知道的那种类型.

你最好的选择是使用std::function; 或者像你一样,然后通过添加强制lambda转换为函数指针+

int main()
{
  wrapper(+[](){std::cout<<"hello."<<std::endl;} );
}
Run Code Online (Sandbox Code Playgroud)

完整示例:

#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;} );
}
Run Code Online (Sandbox Code Playgroud)

这将打印

PRIMARY
hello

SPECIALIZATION
world
Run Code Online (Sandbox Code Playgroud)

此外,decltype设施无济于事,如果确实如此,它将带走您对lambda的需求的灵活性