zoukankan      html  css  js  c++  java
  • C++: double column(class access control qualifier) inhibits type deduction

    在channel 9 上看Stephan T. Lavavej讲Core C++(上channel 9搜索 core C+  part II 即可看到),学到了点trick:

    如果我们写一段这样的代码,让编译器帮我们做template type deduction:

    1 template <typename T> void meow(T val, function<void (T)> f){
    2     f(val);
    3 }
    4 
    5 int main(){
    6     meow(1729,[](int x){cout << "lamda " << x << endl;});
    7 }

    不会通过编译。因为当编译器将lamda [](int x){cout << "lamda " << x << endl;} 向 function<void (T)> 做template type deduction的时候,会失败,因为C++在做template type deduction的时候不会同时做类型转换。即使那个lamda可以通过类型转换成 function<void (T)> ,但是编译器在这里只会做类型推导,不会同时也做隐式类型转换。

    所以,基于以上原因,如果我们要使其能顺利地类型转换通过编译,就应该这样写:

     1 template <typename T> void meow(T val, function<void (T)> f) {
     2     f(val);
     3 }
     4 
     5 int main() {
     6     //这里发生了类型转换
     7     function<void (int)> fxn = [](int x) { cout << "lamda " << x << endl; };
     8 
     9     //很自然的template type deduction,因为fxn的类型就是functioin<void (T)>, 这样,T就会被推导为int
    10     meow(1729, fxn); 
    11 }

    说好的trick呢 ? 在这里:

     1 template <typename T> struct Identity {
     2     typedef T type;
     3 };
     4 
     5 template <typename T> void meow(T val, 
     6     typename Identity<function<void (T)>>::type f) {
     7     f(val);
     8 }
     9 
    10 int main(){
    11 //我可以在这里直接用lamda了 !!Why ?!!!
    12 meow(1729,[](int x)(count << "lamda " << x << endl;});
    13 }

    虽然这段代码有点丑(为了展示这个trick而有意为之),但是还是很有技术含量的。

    首先,来看一些编译器在做argument type deduction的流程:  首先是    T val   , 由于传入了一个1729, 为int类型,所以此时 T 就“有可能“被推导为int。接着,编译器又看到 typename Identity<function<void (T)>>::type f ,这时候他就不会做类型推导了,原因就是这篇文章题目所说的double column(class access control qualifier) inhibits  type deduction当编译器看到 typename Identity<function<void (T)>::type f 的时候, 由于 Identity<function<void (T)>::type 前面有个 typename ,所以他知道 Identity<function<void (T)>::type 是一个类型,然后当编译器想进一步推导的时候,它看到了 type 这个东西前面有一个 :: (access control qualifier),表明 type 是某个namespace 或某个class里面的东西,所以它就不会再进行类型推导了,也就是说这个 :: 阻止了编译器进一步进行类型推导(所谓 double column inhibits type deduction)。所以,编译器的类型推导到这里就结束了。

    那么, Identity<function<void (T)>> 里面的 T 呢? 由于类型推导结束了,那么T的类型自然也就确定了咯,就是在推导 T val 的时候所确定为的 int 。这时候,由于类型推导结束了,那么函数 meow 的参数类型就可以确定为: (int , typename Identity<function<void (int)>>::type ) 了( typename Identity<function<void (T)>>::type 变成了 typename Identity<function<void (int)>>::type ),那么,将lamda  [](int x)(count << "lamda " << x << endl;} 传进去就可以正常地发生隐式类型转换了(由lamda转换成 Identity<function<void (int)>>::type ),所以就可以成功调用了。

    ( source: All the code above are from Stephan T. Lavavej

  • 相关阅读:
    跟一声响骚扰说“拜拜”
    来电过滤 全靠防火墙
    android sd卡读取数据库
    Java程序员十戒
    Java常用的正则表达式验证
    Java 3D 教程:6. Java 3D 与用户界面
    成为Java高手的25个学习目标
    Java数据结构内容整理
    Java中类与类之间的关系
    求助,Java字符串分割问题
  • 原文地址:https://www.cnblogs.com/walkerlala/p/5320251.html
Copyright © 2011-2022 走看看