簡體   English   中英

模板別名 - 問題(C++ 之旅)

[英]Template Aliases - question (tour of c++)

我正在瀏覽 C++ 之旅中的模板別名。 我無法理解下面的代碼以及如何使用它?

template<typename T>
class Vector {
public:
   using value_type = T; 
}

這里他使用 value_type 作為 typename 'T' 的類型別名,為什么我們不能只使用 typename T,因為我們可以將任何類型傳遞給模板(即 class 向量)。 模板需要別名是什么?

template<typename C>
using Value_type = typename C::value_type;

這里 C 的 scope 中的 value_type 是怎樣的,即我們如何使用類型“C”引用 value_type,因為它在 class“向量”內? 'value_type' 這里是指它的向量嗎? 和“Value_type”的意思是 int::Vector 或 string::Vector 等..?

template<typename Container>
void algo(Container &c)
{
  Vector<Value_type<Container>> vec;
}

這三個部分是如何聯系起來的?

為什么是會員別名?

考慮您在其他一些通用代碼中使用Vector的實例化:

template <typename U>
void foo(const U& u);

Vector<int> v;
foo(v);

然后在foo內部,我們需要通過一些箍來 go 找出Tint foo只知道UVector<int> 如果Vector<int>有一個value_type別名,那么訪問它要簡單得多:

template <typename U>
void foo(const U& u) {
    using value_type = typename U::value_type;
    //...
}

現在foo不需要關心U::value_type實際上是VectorT參數,並且對於不是模板實例化的類型也可以:

struct OtherVector {
    using value_type = int;
};
OtherVector ov;
foo(ov);

沒有會員別名:“some hoops”

使用成員別名是一種簡單的方法。 為了完整起見,我想展示讓fooVector<T>推斷T的復雜方法。 你得忍受我...

首先,請注意 function 模板不能部分特化。 這就是為什么我引入一個間接級別:

template <typename U>
struct foo_impl {
    void operator()(const U& u) {
        std::cout << "Hello \n";
    } 
};

template <typename U>
void foo(const U& u) { foo_impl<U>{}(u); }

調用者將調用foo並且在后台我們可以使用foo_impl 例如,我們可以為Vector<T>添加部分規范,我們可以直接訪問T

template <typename T>
struct foo_impl< Vector<T> > {
    void operator()(const Vector<T>& v) {
        std::cout << "Hello Vector<T>\n";
        if constexpr (std::is_same_v<int,T>) {
            std::cout << "T == int\n";
        }
    }
};

活生生的例子

但是,請考慮這對foo意味着什么。 上面的foo適用於任何具有value_type別名的類型。 現在我們有了一個相當無聊的通用定義(打印"Hello" )和Vector<T>的特化(當T==int時打印更多)。 如果我們希望foo也可以使用

 template <typename T>
 struct Bar {};

我們能做什么? 我們可以提供一個更通用的特化來匹配Bar的實例化:

template <template<class> class A, class T>
struct foo_impl< A<T> > {
    void operator()(const A<T>& v) {
        std::cout << "Hello A<T>\n";
        if constexpr (std::is_same_v<int,T>) {
            std::cout << "T == int\n";  // We know what T is when a Vector<T> is passed !!
        }
    }
};

現場示例

它使用模板模板參數來匹配模板的任何實例化與單個模板參數。

我們現在好嗎? 不幸的是,沒有,因為假設我們想從中獲得一個“值類型”:

template <typename A,typename B>
struct Moo {};

假設按照慣例,第一個參數A是我們正在尋找的值類型。 然后我們需要添加一個更通用的特化:

template <template<class...> class A, typename T,typename... Others>
struct foo_impl< A<T,Others...> > {
    void operator()(const A<T,Others...>& v) {
        std::cout << "Hello A<T>\n";
        if constexpr (std::is_same_v<int,T>) {
            std::cout << "T == int\n"; 
        }
    }
};

現場示例

這將匹配具有任意數量類型參數的模板實例化,並將檢測到第一個模板參數為T

我們還好嗎? 不幸的是:一點也不。 以上不符合

template <typename A, int x>
struct Omg {};

因為它有一個非類型模板參數。 我們也可以解決這個問題,但讓我們停在這里。 無論如何,要求值類型始終是第一個參數過於嚴格。

TL;博士

我們真正想要的是讓foo與任何具有關聯“值類型”的類型一起工作。 做到這一點的簡單方法是任何應該傳遞給foo以提供名為value_type的成員別名的類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM