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

Today’s subject is Compile Argument Deduction.

我们平时用template的时候往往需要指定template argument type,实际上很多种情况可以不指定具体的类型,而依赖于编译器的deduction(个人推荐把这个单词翻译成推论,能表达出实际的行为,侯捷翻译这个单词为演绎,可能台湾这么说,总觉得怪怪的)。

先举一个小例子(refer to C++ Templates Chapter 2):

C++ template Day Day Up 第二天 模板参数推论(deduction)template <typename T>
C++ template Day Day Up 第二天 模板参数推论(deduction)T const& Max (T const& a, T const& b)
C++ template Day Day Up 第二天 模板参数推论(deduction){
C++ template Day Day Up 第二天 模板参数推论(deduction) return a > b? a : b;
C++ template Day Day Up 第二天 模板参数推论(deduction)}
C++ template Day Day Up 第二天 模板参数推论(deduction)

看下面的调用:

[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的实现

C++ template Day Day Up 第二天 模板参数推论(deduction)class Any
C++ template Day Day Up 第二天 模板参数推论(deduction){
C++ template Day Day Up 第二天 模板参数推论(deduction)public:
C++ template Day Day Up 第二天 模板参数推论(deduction) class PlaceHolder
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction) public:
C++ template Day Day Up 第二天 模板参数推论(deduction) virtual const std::type_info & type() const = 0;
C++ template Day Day Up 第二天 模板参数推论(deduction)    };
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    template<typename Ty>
C++ template Day Day Up 第二天 模板参数推论(deduction) class Holder
C++ template Day Day Up 第二天 模板参数推论(deduction)        :public PlaceHolder
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction) public:
C++ template Day Day Up 第二天 模板参数推论(deduction)        Holder(Ty const& data)
C++ template Day Day Up 第二天 模板参数推论(deduction)            :_data(data)
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction)        };
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction) virtual const std::type_info & type() const
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction) return typeid(_data);
C++ template Day Day Up 第二天 模板参数推论(deduction)        }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction) public:
C++ template Day Day Up 第二天 模板参数推论(deduction)        Ty _data;
C++ template Day Day Up 第二天 模板参数推论(deduction)    };
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)public:
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    Any()
C++ template Day Day Up 第二天 模板参数推论(deduction)        :_holder(0)
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction)    }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    template<typename T>
C++ template Day Day Up 第二天 模板参数推论(deduction)    Any(T const& ty)
C++ template Day Day Up 第二天 模板参数推论(deduction)        :_holder(new Holder<T>(ty))
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction)        cout<<"Con:"<<typeid(ty).name()<<endl;
C++ template Day Day Up 第二天 模板参数推论(deduction)    }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    template<typename T>
C++ template Day Day Up 第二天 模板参数推论(deduction)    Any& operator=(const T& rh)
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction) if (!_holder)
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction)            delete _holder;
C++ template Day Day Up 第二天 模板参数推论(deduction)        }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)        cout<<"Op=:"<<typeid(rh).name()<<endl;
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)        _holder = new Holder<T>(rh);
C++ template Day Day Up 第二天 模板参数推论(deduction) return *this;
C++ template Day Day Up 第二天 模板参数推论(deduction)    }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction) const std::type_info & type() const
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction) return _holder ? _holder->type() : typeid(void);
C++ template Day Day Up 第二天 模板参数推论(deduction)    }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction) ~Any()
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction)        delete _holder;
C++ template Day Day Up 第二天 模板参数推论(deduction)    }
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)private:
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    template<typename ResultType>
C++ template Day Day Up 第二天 模板参数推论(deduction)    friend    ResultType* Any_cast(Any* operand);
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    PlaceHolder* _holder;
C++ template Day Day Up 第二天 模板参数推论(deduction)};
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)template<typename ResultType>
C++ template Day Day Up 第二天 模板参数推论(deduction)ResultType* Any_cast(Any* operand)
C++ template Day Day Up 第二天 模板参数推论(deduction){
C++ template Day Day Up 第二天 模板参数推论(deduction) return operand && (operand->type() == typeid(ResultType))
C++ template Day Day Up 第二天 模板参数推论(deduction) ? &static_cast<Any::Holder<ResultType> *>(operand->_holder)->_data : 0;
C++ template Day Day Up 第二天 模板参数推论(deduction)}
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)main函数中:
C++ template Day Day Up 第二天 模板参数推论(deduction)    vector<int> vo;
C++ template Day Day Up 第二天 模板参数推论(deduction)    vo.push_back(1);
C++ template Day Day Up 第二天 模板参数推论(deduction)    vo.push_back(2);
C++ template Day Day Up 第二天 模板参数推论(deduction)    Any a = 5;
C++ template Day Day Up 第二天 模板参数推论(deduction)    a = vo;
C++ template Day Day Up 第二天 模板参数推论(deduction)
C++ template Day Day Up 第二天 模板参数推论(deduction)    vector<int>* v = Any_cast<vector<int> >(&a);
C++ template Day Day Up 第二天 模板参数推论(deduction) for (vector<int>::iterator it = (*v).begin(); it != (*v).end(); ++it)
C++ template Day Day Up 第二天 模板参数推论(deduction) {
C++ template Day Day Up 第二天 模板参数推论(deduction)        cout<<*it<<endl;
C++ template Day Day Up 第二天 模板参数推论(deduction)    }
C++ template Day Day Up 第二天 模板参数推论(deduction)

相关文章:

  • 2021-12-05
  • 2021-10-31
  • 2022-12-23
  • 2022-01-24
  • 2021-06-07
  • 2021-08-12
  • 2022-12-23
  • 2021-12-28
猜你喜欢
  • 2021-12-13
  • 2021-10-22
  • 2021-11-15
  • 2021-06-01
  • 2021-10-29
  • 2022-12-23
相关资源
相似解决方案