mercredi 16 août 2017

Template Template Arguments Inconsistent with Deduced Template Arguments

The following code fails to compile with the error 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);
}

The original intention behind this code is irrelevant, at this point I'm just trying to understand why this is considered to be invalid.

If I change the call to std::make_tuple into std::make_pair, the code compiles and runs correctly, which leads me to believe there's something weird going on that's specific to std::tuple.

I was originally thinking that std::tuple might have some extra, defaulted, template arguments I wasn't aware of, because if I change the definition of print_tuploid to the following, the code DOES compile for both std::make_tuple and 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;
}

But when I tried to dump out the deduced type of stuff using the following code:

#include <tuple>

template<typename T>
class TypePrinter;

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

It reported: implicit instantiation of undefined template 'TypePrinter<std::__1::tuple<int, int> >', leading me to believe this is not the case.

Also, as a side question, why does reference collapsing not occur in this context? The following code is also considered invalid:

#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);
}

Giving the error: no known conversion from 'std::__1::pair<int, int>' to 'pair<int, int> &&' for 1st argument.

Basically I'm just trying to extend my template knowledge by understanding what exactly is going on here. Sorry for the long post, and thanks in advance for any guidance anyone is able to provide.

Aucun commentaire:

Enregistrer un commentaire