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