C++ template Day Day Up 第二天 模板参数推论(deduction)

转载 2007年09月27日 08:18:00
Today’s subject is Compile Argument Deduction.
 
我们平时用template的时候往往需要指定template argument type,实际上很多种情况可以不指定具体的类型,而依赖于编译器的deduction(个人推荐把这个单词翻译成推论,能表达出实际的行为,侯捷翻译这个单词为演绎,可能台湾这么说,总觉得怪怪的)。
先举一个小例子(refer to C++ Templates Chapter 2):
 
 
template <typename T> 
const& Max (T const& a, T const& b)
...{
  
return a > b? a : b;
}

看下面的调用:
[a] Max(1, 2);
[b] Max(‘c’, ‘d’);
[c] Max(5.5, 7);
[d] Max(5.5, static_cast<double>(7) );
[e] Max<double>(5.5, 7);
 
让我们先关注[a]、[b]、[c]
调用Max模板函数的时候并没有指定模板参数!这个就是编译器为我们所作的Argument Deduction。
编译器会根据传进去的变量推断出它的类型,[a]中compiler会生成Max<int>版本的函数,[b]则会生成Max<char>版本的函数。
那么[c]呢?
答案是compiler会报告一个错误,
VS2005中文版下:error C2782: “T Max(const T &,const T &)”: 模板参数“T”不明确
G++ :error: no matching function for call to `Max(double, int)'
请注意,Max函数的定义要求a和b是同一类型,也就是说compiler对于[c]推断不出匹配的函数。解决这个问题我们可以采用[d]或者[e]的方式调用Max函数。
 
另外,编译器对于类的成员函数也可以进行Deduction,看下面的例子:
class Any
{
public:
 
     template<typename T>
     Any(T const& ty)
     {
     }
};
 
这个Any类提供一个带模板的构造函数,编译器可以为这种成员函数进行类型推论,这会给这个类一种特别的威力。
int i = 5;
string s;
stack<string> st;
vector<int> v;
Any a = i;
Any b = s;
Any c = st;
Any d = v;
上面的代码竟然能够编译!
这会为C++带来什么,Any类是void*么?不是,Any类更像是java中的Object,它比void*强在它可以存储具体类型,当向下转换的时候,也更安全。
 
上面的说明可能您不太相信,建议看一下boost库的any的实现。文章的最后给出了我参考boost写的简略版的any的实现,代码忽略了很多细节,只突出重要思想(Boost是any,这里是Any),有兴趣可以看一下。
 
注意!只有函数或者成员函数才能够进行argument deduction。
 
Argument deduction还会为我们带来什么?
我比较欣赏的是编译期多态,Design Pattern的template版本会很有意思,以后的文章会介绍到。
Summary
写着写着就觉得稍微写深了,本来只想写函数模板,真是水平不济啊!
本人希望读这系列文章的读者能够熟悉C++非模板的语法和应用,并且最好能够熟悉面向对象(之后的文章可能会涉及一些Design Pattern),能写出真正的面向对象程序。
并且希望写作水平有所提高,可以在模板基础知识之间,穿插一些实际的应用,希望每一篇blog都会给不太了解模板的程序员一点帮助。
 
附录:
缩略版Any的实现
 
class Any
...{
public:
    
class PlaceHolder
    
...{
    
public:
        
virtual const std::type_info & type() const = 0;
    }
;

    template
<typename Ty>
    
class Holder
        :
public PlaceHolder
    
...{
    
public:
        Holder(Ty 
const& data)
            :_data(data)
        
...{
        }
;

        
virtual const std::type_info & type() const
        
...{
            
return typeid(_data);
        }


    
public:
        Ty _data;
    }
;

public:

    Any()
        :_holder(
0)
    
...{
    }


    template
<typename T>
    Any(T 
const& ty)
        :_holder(
new Holder<T>(ty))
    
...{
        cout
<<"Con:"<<typeid(ty).name()<<endl;
    }


    template
<typename T>
    Any
& operator=(const T& rh)
    
...{
        
if (!_holder)
        
...{
            delete _holder;
        }


        cout
<<"Op=:"<<typeid(rh).name()<<endl;

        _holder 
= new Holder<T>(rh);
        
return *this;
    }


    
const std::type_info & type() const
    
...{
        
return _holder ? _holder->type() : typeid(void);
    }


    
~Any()
    
...{
        delete _holder;
    }


private:

    template
<typename ResultType>
    friend    ResultType
* Any_cast(Any* operand);

    PlaceHolder
* _holder;
}
;

template
<typename ResultType>
ResultType
* Any_cast(Any* operand)
...{
    
return operand && (operand->type() == typeid(ResultType))
        
? &static_cast<Any::Holder<ResultType> *>(operand->_holder)->_data : 0;
}


main函数中:
    vector
<int> vo;
    vo.push_back(
1);
    vo.push_back(
2);
    Any a 
= 5;
    a 
= vo;

    vector
<int>* v = Any_cast<vector<int> >(&a);
    
for (vector<int>::iterator it = (*v).begin(); it != (*v).end(); ++it)
    
...{
        cout
<<*it<<endl;
    }

 
 

使用Calendar获取DAY_OF_WEEK本周开始和结束的时间戳

和获取今日开始和结束的时间戳一样,本周开始和结束的时间戳,就是以本周第一天开始的00:00到本周最后一天的23:59分结束。 需要注意的是,国际上是以星期日为一周第一天的开始,Calendar中提供...
  • zhuwentao2150
  • zhuwentao2150
  • 2016年08月01日 12:56
  • 8858

Django模板系统详解(四)

你可能已经注意到我们在例子视图中返回文本的方式有点特别。也就是说,HTML被硬性地直接写入 Python 代码之中。 这种处理会导致一些问题: § 对页面设计的进行任何改变都必须对 Python 代码...
  • wolaiye320
  • wolaiye320
  • 2016年07月05日 17:15
  • 3272

模板函数的参数类型不能通过表达式推导

2down votefavorite I want to implement a container which can accept initial list of...
  • jfkidear
  • jfkidear
  • 2015年02月02日 14:13
  • 2285

《Effective Modern C++》读书笔记(1) -- 模板类型推导(template type deduction)

前段时间看了《Effective Modern C++》这本书,收获颇多,书中讲解了许多C++11/14的特性,都是之前不太了解或者模糊的,看了之后茅塞顿开,强烈建议C++学习者看一看。现在是第二遍,...
  • tutuxs
  • tutuxs
  • 2017年05月14日 13:10
  • 348

<Effective Mordern C++>笔记:Item 1: Understand the template type deduction.

写在前面: 基础的东西学完之后,最好的进阶方式就是项目+啃书了,项目也在准备当中,啃书还是绝对不能落下的。现在C++11/14已经成为主流,正好在图书馆借到了《Effective Mordern ...
  • cqk0100
  • cqk0100
  • 2017年05月02日 22:54
  • 110

传智播客崔希凡JavaWeb-day16-mysql第二天-全部资料

  • 2014年12月08日 16:36
  • 487KB
  • 下载

C++ - 可变参数函数模板(Variadic Function Template) 详解 及 代码

可变参数函数模板(Variadic Function Template) 详解 及 代码 本文地址: http://blog.csdn.net/caroline_wendy/article/det...
  • u012515223
  • u012515223
  • 2013年12月02日 17:19
  • 6253

C++ -- variadic template (可变参数模板)

C++11 语言核心的改进中,最为关注的有 rvalue reference (这里有一篇拙作),lambda,variadic template。rvalue 规则稍微复杂,但一旦理解和记住了,...
  • e295166319
  • e295166319
  • 2017年05月02日 18:31
  • 130

C++ - 非类型模板参数(nontype template parameters) 使用 及 代码

非类型模板参数(nontype template parameters) 使用 及 代码 本文地址: http://blog.csdn.net/caroline_wendy/article/det...
  • u012515223
  • u012515223
  • 2013年12月09日 14:16
  • 6719

Symfony2 Jobeet Day 1:Starting up the Project PDF

  • 2013年11月19日 15:07
  • 2.45MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ template Day Day Up 第二天 模板参数推论(deduction)
举报原因:
原因补充:

(最多只允许输入30个字)