2017-08-17 197 views
4

下面的代碼失敗,出現錯誤template template argument has different template parameters than its corresponding template template parameter編譯:模板模板參數不符合推導的模板參數

#include <tuple> 
#include <vector> 
#include <string> 
#include <iostream> 

template<template<typename, typename> class Blah, typename KeyType, typename ValueType> 
void print_tuploid(const Blah<KeyType, ValueType>& tup) { 
    std::cout << "first value: " << std::get<0>(tup) << " second value: " << std::get<1>(tup) << std::endl; 
} 

int main() { 
    auto stuff = std::make_tuple(1, 2); 
    print_tuploid(stuff); 
} 

這段代碼背後的初衷是無關緊要的,在這一點上,我只是想了解爲什麼這個被認爲是無效的。

如果我將std::make_tuple更改爲std::make_pair,代碼編譯並正確運行,這導致我相信有一些奇怪的事情發生在std::tuple

我最初的想法是std::tuple可能有一些額外的,違約,模板參數,我是不知道的,因爲如果我改變的print_tuploid定義爲以下的代碼不會編譯兩個std::make_tuplestd::make_pair

template<template<typename...> class Blah, typename KeyType, typename ValueType> 
void print_tuploid(const Blah<KeyType, ValueType>& tup) { 
    std::cout << "first value: " << std::get<0>(tup) << " second value: " << std::get<1>(tup) << std::endl; 
} 

但是,當我嘗試使用下面的代碼傾倒了推導型的stuff

#include <tuple> 

template<typename T> 
class TypePrinter; 

int main() { 
    auto stuff = std::make_tuple(1, 2); 
    TypePrinter<decltype(stuff)> error; 
} 

據報道:implicit instantiation of undefined template 'TypePrinter<std::__1::tuple<int, int> >',讓我相信事實並非如此。

此外,作爲一個側面問題,爲什麼在這種情況下引用崩潰不會發生?以下代碼也被認爲無效:

#include <iostream> 

template<template<typename, typename> class Blah, typename KeyType, typename ValueType> 
void print_tuploid(Blah<KeyType, ValueType>&& tup) { 
    std::cout << "first value: " << std::get<0>(tup) << " second value: " << std::get<1>(tup) << std::endl; 
} 

int main() { 
    auto stuff = std::make_pair(1, 2); 
    print_tuploid(stuff); 
} 

給出錯誤:no known conversion from 'std::__1::pair<int, int>' to 'pair<int, int> &&' for 1st argument

基本上我只是想通過理解這裏究竟發生了什麼來擴展我的模板知識。很抱歉,很長的文章,並提前感謝任何人都可以提供的任何指導。

+0

現在無法展開爲完整的帖子,但將精確的模板參數與參數包匹配被認爲是不正確的。有一篇論文,但我忘記它是否被接受到17中。 – user975989

+0

參考摺疊發生在像'T &&'這樣的參數上 - 如果'T'被推斷爲左值參考,則它是左值參考,否則就是右值參考。 'Blah '不可能被推斷爲左值引用類型 - 這顯然是一個類類型。 –

回答

4

該函數的問題在於它與一個僅佔用2個參數的模板類相匹配。實際上,std::tuple的模板簽名爲template <typename...>。區別在於tuple需要任意數量的模板參數,而您的函數需要2.

std::pair工作正常,因爲模板簽名是template <typename, typename>,它完全匹配。

有一個建議,雖然我無法找到最新版本,使這種專業化。它似乎已經傳遞到C++ 17中,或者至少類似於它,因爲模板模板參數的cppreference頁面認爲這是一個有效的示例。我找到的建議是here

你的第二個版本不接受std::pair的原因是因爲它期望一個右值引用。一旦你有(部分)專業類型,你不能把&&作爲轉發參考。