以下代码无法使用错误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_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;
}
但是当我尝试使用以下代码转储推导出的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 :(得分:5)
该函数的问题在于它与一个只需要2个参数的模板类匹配。实际上,std::tuple
的模板签名为template <typename...>
。区别在于tuple
采用任意数量的模板参数,而您的函数需要2。
std::pair
工作正常,因为模板签名是template <typename, typename>
,它完全匹配。
虽然我无法找到最新版本,但有一项提案可以实现这种专业化。它似乎已经传入C ++ 17,或者至少与它类似,因为模板模板参数的cppreference页面认为这是一个有效的例子。我找到的提案是here。
您的第二个版本不接受std::pair
的原因是因为它需要一个右值引用。拥有(部分)专用类型后,您无法将&&
视为转发参考。