模板模板参数不符合推导的模板参数

模板模板参数不符合推导的模板参数

问题描述:

下面的代码失败,出现错误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 '不可能被推断为左值引用类型 - 这显然是一个类类型。 –

该函数的问题在于它与一个仅占用2个参数的模板类相匹配。实际上,std::tuple的模板签名为template <typename...>。区别在于tuple需要任意数量的模板参数,而您的函数需要2.

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

有一个建议,虽然我无法找到最新版本,使这种专业化。它似乎已经传递到C++ 17中,或者至少类似于它,因为模板模板参数的cppreference页面认为这是一个有效的示例。我找到的建议是here

你的第二个版本不接受std::pair的原因是因为它期望一个右值引用。一旦你有(部分)专业类型,你不能把&&作为转发参考。