模板模板参数与推导的模板参数不一致

Chr*_*etz 5 c++ templates c++11

以下代码无法编译并显示以下错误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);
}
Run Code Online (Sandbox Code Playgroud)

该代码背后的初衷无关紧要,在这一点上,我只是想了解为什么认为这是无效的。

如果将调用更改std::make_tuplestd::make_pair,则代码会正确编译并运行,这使我相信特定于的事情很奇怪std::tuple

我最初以为std::tuple可能会有一些我不知道的额外的默认模板参数,因为如果我将以下定义更改为print_tuploid,则代码会同时为std::make_tuple和编译std::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;
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试转储stuff使用以下代码的推导类型时:

#include <tuple>

template<typename T>
class TypePrinter;

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

它报告: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);
}
Run Code Online (Sandbox Code Playgroud)

给出错误:no known conversion from 'std::__1::pair<int, int>' to 'pair<int, int> &&' for 1st argument

基本上,我只是想通过了解到底发生了什么来扩展我的模板知识。很抱歉,冗长的帖子,在此先感谢任何人都可以提供的任何指导。

use*_*989 5

该函数的问题在于,它与正好带有2个参数的模板类匹配。实际上,std::tuple具有的模板签名template <typename...>。区别在于它tuple需要任意数量的模板参数,而您的函数需要2。

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

有一个建议,尽管我找不到最新版本,但可以启用这种专业化。它似乎已经传入C ++ 17或至少与之类似的东西,因为模板模板参数的cppreference页认为这是一个有效的示例。我找到的建议在这里

第二个版本不接受std::pair的原因是因为它需要右值引用。一旦拥有(部分)专用类型,就不能将其&&视为转发参考。