模板模板参数不符合推导的模板参数
下面的代码失败,出现错误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
。
基本上我只是想通过理解这里究竟发生了什么来扩展我的模板知识。很抱歉,很长的文章,并提前感谢任何人都可以提供的任何指导。
该函数的问题在于它与一个仅占用2个参数的模板类相匹配。实际上,std::tuple
的模板签名为template <typename...>
。区别在于tuple
需要任意数量的模板参数,而您的函数需要2.
std::pair
工作正常,因为模板签名是template <typename, typename>
,它完全匹配。
有一个建议,虽然我无法找到最新版本,使这种专业化。它似乎已经传递到C++ 17中,或者至少类似于它,因为模板模板参数的cppreference页面认为这是一个有效的示例。我找到的建议是here。
你的第二个版本不接受std::pair
的原因是因为它期望一个右值引用。一旦你有(部分)专业类型,你不能把&&
作为转发参考。
现在无法展开为完整的帖子,但将精确的模板参数与参数包匹配被认为是不正确的。有一篇论文,但我忘记它是否被接受到17中。 – user975989
参考折叠发生在像'T &&'这样的参数上 - 如果'T'被推断为左值参考,则它是左值参考,否则就是右值参考。 'Blah'不可能被推断为左值引用类型 - 这显然是一个类类型。 –