2016-11-16 38 views
0

基本上,我想打一個函數的行爲不同的向量(類型)參數和非矢量類型參數。C++如何使用向量專門化模板<T>?

#include <vector> 
using namespace std; 

template <typename type> 
struct is_vector { 
    static const bool value = false; 
}; 

template <typename type> 
struct is_vector<vector<type>> 
{ 
    static const bool value = true; 
}; 
template <typename type> 
type read() 
{ 
    if (is_vector<type>::value) 
    {  
     type vec(10); 
     vec.front()=1;//left of '.front' must have class/struct/union 
     return vec; 
    } 
    else 
    { 
     return{}; 
    } 
} 
int main() 
{ 
    auto i= read<int>(); 
} 

我想在矢量使用的類型名稱返回一個載體,同時使用INT作爲類型名返回一個int。

但由於is_vector(INT)::,爲什麼我的編譯器報告「左‘.front’必須有類/結構/聯合」?我怎樣才能使它工作值返回false?

我想達到什麼是正確反序列化一個字符串向量(類型)或向量(矢量(種))。

我需要遞歸調用的讀取功能,同時傳遞一個multidemonsional載體作爲模板參數,但是編譯器不允許我這樣做。

template <typename type> 
struct is_vector { 
    static const bool value = false; 
}; 

template <typename type> 
struct is_vector<vector<type>> 
{ 
    static const bool value = true; 
}; 

template <typename type> 
type read(char*& str) 
{ 
    if (is_vector<type>::value) 
    {  
     type vec(read<uint8_t>(str)); 
     for (auto& e : vec) 
      e = read<type::value_type>(str); 
     return vec; 
    } 
    return *reinterpret_cast<type*>((str += sizeof(type)) - sizeof(type)); 
} 

所以我嘗試了專業化。

template<> 
vector<int> read<vector<int>>(char*& str) 
{ 
    vector<int> vec(read<uint8_t>(str)); 
    for (auto& e : vec) 
     e = read<int>(str); 
    return vec; 
}//works 

template <typename type> 
template <> 
vector<type> read<vector<type>>(char*& str) 
{ 
    vector<type> vec(read<uint8_t>(str)); 
    for (auto& e : vec) 
     e = read<type>(str); 
    return vec; 
}//don't work 

我真的需要手動重寫我讀功能爲每一種類型的怎麼用?

(如向量(矢量(向量(INT)))?)

+0

你用於向量檢查是*遊程時間*檢查。該分支中的所有代碼仍然需要編譯。 –

+0

首先:'is_vector'謂詞在編譯時被評估。在if中使用它表示您沒有完全明白應該使用哪些模板。 – Albjenow

+0

@Albjenow我不太瞭解元編程,我怎樣才能讓我的函數爲矢量和pod類型生成不同的代碼? – iouvxz

回答

2

你想要一個函數模板foo<R>即參數至少 返回類型R,和你想有一個專門的實現 當R = std::vector<U> ,適用於任意類型U

無論什麼foo<R>的參數可能是什麼,所以爲了說明 我們假設沒有任何。這裏是你如何做到這一點:

定義特質模板如下:

template<typename T> 
struct is_vector 
{ 
    static constexpr bool value = false; 
}; 

template<template<typename...> class C, typename U> 
struct is_vector<C<U>> 
{ 
    static constexpr bool value = 
     std::is_same<C<U>,std::vector<U>>::value; 
}; 

有了這個,

is_vector<T>::value 

將是真實的,在編譯時,當且僅當T = std::vector<U>,爲一些U

然後在以下行定義的foo<R>()兩個重載:

template <typename R> 
std::enable_if_t<!is_vector<R>::value,R> foo() 
{ 
    // Your non-vector implementation instead of... 
    std::cout << 
     "In non-vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

template <typename R> 
std::enable_if_t<is_vector<R>::value,R> foo() 
{ 
    // Your vector implementation instead of... 
    std::cout << 
     "In vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

這兩個重載是相互排斥的,共同窮盡的。當且僅當is_vector<R>::value爲假時, 第一次重載才能成爲合法代碼。當且僅當is_vector<R>::value爲真時, 第二次重載才能成爲合法代碼。 這得益於std::enable_if行爲, 你應該研究和理解。

當編譯器需要選擇一個模板,這些重載實現一些 調用foo<type>()它發現在你的代碼,它發現重載 的只有一個時type插在模板參數甚至不會編譯R。第一個將無法編譯,如果 type一些std::vector<U>如果type一些 std::vector<U>第二個將不編譯。有用的是,編譯器選擇它可以編譯的。 這就是所謂的SFINAE ("Substitution Failure Is Not An Error"), 它是你的問題的解決方案。

下面是一個說明性程序:

#include <vector> 
#include <type_traits> 
#include <iostream> 

template<typename T> 
struct is_vector 
{ 
    static constexpr bool value = false; 
}; 

template<template<typename...> class C, typename U> 
struct is_vector<C<U>> 
{ 
    static constexpr bool value = 
     std::is_same<C<U>,std::vector<U>>::value; 
}; 

template <typename R> 
std::enable_if_t<!is_vector<R>::value,R> foo() 
{ 
    // Your non-vector implementation instead of... 
    std::cout << 
     "In non-vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

template <typename R> 
std::enable_if_t<is_vector<R>::value,R> foo() 
{ 
    // Your vector implementation instead of... 
    std::cout << 
     "In vector specialization of `foo<R>()`\n"; 
    return R(); 
} 

int main() 
{ 
    auto i = foo<int>(); 
    (void)i; 
    auto vc = foo<std::vector<char>>(); 
    (void)vc; 
    return 0; 
} 

其中將輸出:

In non-vector specialization of `foo<R>()` 
In vector specialization of `foo<R>()` 

(GCC 6.1 /鐺3.8,-std=c++14see live