亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

模板參數的一些用途是什么?

模板參數的一些用途是什么?

C++
繁星淼淼 2019-06-29 17:12:57
模板參數的一些用途是什么?我看到了一些使用模板參數(即以模板作為參數的模板)來進行基于策略的類設計的C+示例。這項技術還有什么其他用途?
查看完整描述

3 回答

?
Helenr

TA貢獻1780條經驗 獲得超4個贊

我認為您需要使用模板語法來傳遞一個參數,該參數的類型依賴于另一個模板,如下所示:

template <template<class> class H, class S>void f(const H<S> &value) {}

這里,H是一個模板,但我希望這個函數能夠處理H.

:我已經編程c+很多年了,而且只需要一次。我發現它是一個很少需要的特性(當然,當您需要它時,它非常方便!)

我一直在努力想出好的例子,老實說,大多數時候這是不必要的,但讓我們想一個例子。讓我們假裝std::vector typedef value_type.

那么,如何編寫一個可以為向量元素創建正確類型的變量的函數呢?這樣就行了。

template <template<class, class> class V, class T, class A>void f(V<T, A> &v) {
    // This can be "typename V<T, A>::value_type",
    // but we are pretending we don't have it

    T temp = v.back();
    v.pop_back();
    // Do some work on temp

    std::cout << temp << std::endl;}

*我們std::vector有兩個模板參數,類型和分配器,所以我們必須同時接受它們。幸運的是,由于類型推斷,我們不需要顯式地寫出確切的類型。

你可以這樣用:

f<std::vector, int>(v); // v is of type std::vector<int> using any allocator

或者更好的是,我們可以用:

f(v); // everything is deduced, f can deal with a vector of any type!

更新:即使這個人為的例子,雖然具有說明性,但由于c+11的引入,已經不再是一個令人驚奇的例子了。auto..現在,可以將相同的函數編寫為:

template <class Cont>void f(Cont &v) {

    auto temp = v.back();
    v.pop_back();
    // Do some work on temp

    std::cout << temp << std::endl;}

這就是我更喜歡寫這種類型的代碼的方式。


查看完整回答
反對 回復 2019-06-29
?
臨摹微笑

TA貢獻1982條經驗 獲得超2個贊

實際上,模板參數的使用是相當明顯的。一旦您了解到C+stdlib存在不為標準容器類型定義流輸出操作符的漏洞,就可以編寫如下內容:

template<typename T>static inline std::ostream& operator<<(std::ostream& out, std::list<T> const& v){
    out << '[';
    if (!v.empty()) {
        for (typename std::list<T>::const_iterator i = v.begin(); ;) {
            out << *i;
            if (++i == v.end())
                break;
            out << ", ";
        }
    }
    out << ']';
    return out;}

然后你會發現向量的代碼是一樣的,因為Forward_List是一樣的,實際上,即使對于多種地圖類型,它仍然是一樣的。除了元接口/協議之外,這些模板類沒有任何共同之處,使用模板參數可以捕獲所有模板的共性。但是,在繼續編寫模板之前,值得檢查一個引用,以回顧序列容器接受2個模板參數-用于值類型和分配器。雖然分配器是默認的,但我們仍然應該在模板操作符<:

template<template <typename, typename> class Container, class V, class A>std::ostream& operator<<(std::ostream& out, Container<V, A> const& v)...

瞧,這將自動工作,所有現在和未來的序列容器符合標準協議。要將映射添加到混合中,需要查看一下引用,注意它們接受4個模板參數,因此我們需要操作符<上面的另一個版本,使用4-Arg模板param。我們還會看到,std:偶對嘗試使用2-Arg操作符<for我們前面定義的序列類型來呈現,因此我們將只為std:偶數提供專門化。

順便說一句,使用C+11(允許可變模板)(因此應該允許可變模板args),可以讓單個操作符<來統治所有這些模板。例如:

#include <iostream>#include <vector>#include <deque>#include <list>template<typename T, template<class,class...> class C, class... Args>std::ostream& operator <<(std::ostream& os, const C<T,Args...>& objs){
    os << __PRETTY_FUNCTION__ << '\n';
    for (auto const& obj : objs)
        os << obj << ' ';
    return os;}int main(){
    std::vector<float> vf { 1.1, 2.2, 3.3, 4.4 };
    std::cout << vf << '\n';

    std::list<char> lc { 'a', 'b', 'c', 'd' };
    std::cout << lc << '\n';

    std::deque<int> di { 1, 2, 3, 4 };
    std::cout << di << '\n';

    return 0;}

輸出量

std::ostream &operator<<(std::ostream &, const C<T, Args...> &) [T = float, C = vector, Args = <std::__1::allocator<float>>]1.1 2.2 3.3 4.4 std::ostream &operator<<(std::ostream &, const C<T, Args...> &) [T = char, C = list, Args = <std::__1::allocator<char>>]a b c d 
std::ostream &operator<<(std::ostream &, const C<T, Args...> &) [T = int, C = deque, Args = <std::__1::allocator<int>>]1 2 3 4


查看完整回答
反對 回復 2019-06-29
?
天涯盡頭無女友

TA貢獻1831條經驗 獲得超9個贊

下面是一個簡單的例子“現代C+設計-通用編程和應用設計模式”安德烈·亞歷山德雷斯庫:

他使用帶有模板參數的類來實現策略模式:

// Library codetemplate <template <class> class CreationPolicy>class WidgetManager : public CreationPolicy<Widget>{
   ...};

他解釋說:通常,宿主類已經知道或可以很容易地推斷策略類的模板參數。在上面的示例中,WidgetManager總是管理Widget類型的對象,因此要求用戶在CreationPolicy的實例化中再次指定Widget是多余的,而且可能很危險。在這種情況下,庫代碼可以使用模板參數來指定策略。

其效果是客戶端代碼可以更優雅地使用“WidgetManager”:

typedef WidgetManager<MyCreationPolicy> MyWidgetMgr;

而不是缺乏模板參數的定義所需要的更麻煩、更容易出錯的方式:

typedef WidgetManager< MyCreationPolicy<Widget> > MyWidgetMgr;


查看完整回答
反對 回復 2019-06-29
  • 3 回答
  • 0 關注
  • 736 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號