是否有可能明确专门化模板来匹配lambda? [英] Is it possible to explicitly specialize template to match lambda?

查看:138
本文介绍了是否有可能明确专门化模板来匹配lambda?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个头 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上专门化模板?


不幸的是,模板专业化与确切匹配,并且 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 <<hello\\\
<< 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:

Is it possible to specialize a template on a lambda?

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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆