3

This is a followup to this question.

I'm having a templated type with a template template argument

template <template <typename...> class CONTAINER, typename NUMBERTYPE>
struct spam {
    template <class T>
    using Temp = CONTAINER<T>;
};

I want to write a (templated) function that takes a spam instance and returns a spam instance of a slightly different type. I want to maintain the CONTAINER template parameter from the input and only specify the NUMBERTYPE. (godbolt link)

#include <type_traits>
#include <vector>

template <template <typename...> class CONTAINER, typename NUMBERTYPE>
struct spam {
    template <class T>
    using Temp = CONTAINER<T>;
};

template <typename T>
auto function(T in) {
    spam<T::template Temp, double> retval;
    return retval;
}

int main() {
    spam<std::vector, float> one;
    // spam<std::vector, double> two = function(one);
    auto two = function(one);
    return 0;
}

This mostly works, but I wanted to check if function() returns the type I expected by receiving the expected spam<std::vector, double> rather than accepting an auto return. The non-auto version does not compile because

<source>:18:45: error: conversion from 'spam<spam<std::vector, float>::Temp,[...]>' to non-scalar type 'spam<std::vector,[...]>' requested

     spam<std::vector, double> two = function(one);

                                     ~~~~~~~~^~~~~

i.e. I have a mismatch between spam<std::vector, double> and spam<spam<std::vector, float>::template Temp, doulbe>, although I expect that spam<std::vector, float>::template Temp is the same as std::vector. (In fact I can check that std::is_same_v<spam<std::vector, float>::template Temp<int>, std::vector<int>> is indeed true - i.e. after providing the template arguments to Temp I have expected/desired behaviour, just that the code I'm contributing to works mostly with the unresolved CONTAINER).

QUESTION: is there a way to normalize T::template Temp to whatever it is and remove the spam<...>::Temp from the type?

max66
  • 65,235
  • 10
  • 71
  • 111
pseyfert
  • 3,263
  • 3
  • 21
  • 47
  • 1
    Not that this nitpick helps you, but `T::template Temp` is _not_ a type, contrary to what your last sentence says. – Max Langhof May 06 '19 at 16:56

1 Answers1

4

QUESTION: is there a way to normalize T::template Temp to whatever it is and remove the spam<...>::Temp from the type?

No, as far I know.

But isn't necessary, in this case, because you can rewrite function() to intercept the template-template parameter CONTAINER.

I mean: you can rewrite function() as follows

template <template <typename...> class C, typename N>
spam<C, double> function (spam<C, N> const &)
 { return {}; }

The following is a full compiling example

#include <type_traits>
#include <vector>

template <template <typename...> class CONTAINER, typename NUMBERTYPE>
struct spam
 {
   template <typename T>
   using Temp = CONTAINER<T>;
 };

template <template <typename...> class C, typename N>
spam<C, double> function (spam<C, N> const &)
 { return {}; }

int main() {
    spam<std::vector, float> one;
    spam<std::vector, double> two = function(one);
    auto three = function(one);
}
max66
  • 65,235
  • 10
  • 71
  • 111