I am writing a meta function replace_type<C, X, Y>that should replace all type matches Xin a composite type Cwith Y. I am currently working on making this work correctly with callables in C.
It works:
template replace_type<
typename C, typename X, typename Y,
typename First
>
struct replace_type<C(First), X, Y>
{
typedef typename replace_type<
C, X, Y
>::type type(
typename replace_type<
First, X, Y
>::type
);
};
template replace_type<
typename C, typename X, typename Y,
typename First, typename Second
>
struct replace_type<C(First, Second), X, Y>
{
typedef typename replace_type<
C, X, Y
>::type type(
typename replace_type<
First, X, Y
>::type,
typename replace_type<
Second, X, Y
>::type
);
};
But this is obviously very limited. It was obvious in my head that I should use a variation pattern instead, but when I really tried to apply it, I quickly noticed that I had no idea how to put it in this diagram.
I thought of its implementation as follows:
template replace_type<
typename C, typename X, typename Y,
typename First, typename... Args
>
struct replace_type<C(First, Args...), X, Y>
{
typedef typename replace_type<
C, X, Y
>::type type(
typename replace_type<
First, X, Y
>::type,
);
};
, , , , . , , ?
:
#include <type_traits>
namespace type_replace_helper
{
template <typename, typename, typename>
struct type_replace_base;
}
template <typename C, typename X, typename Y>
struct type_replace
{
typedef typename std::conditional<
std::is_same<C, X>::value,
Y,
typename type_replace_helper::type_replace_base<
C, X, Y
>::type
>::type type;
};
namespace type_replace_helper
{
template <typename C, typename X, typename Y>
struct type_replace_base
{
typedef C type;
};
template <typename C, typename X, typename Y>
struct type_replace_base<C(), X, Y>
{
typedef typename type_replace<
C, X, Y
>::type type();
};
template <
typename C, typename X, typename Y,
typename First
>
struct type_replace_base<C(First), X, Y>
{
typedef typename type_replace<
C, X, Y
>::type type(
typename type_replace<
First, X, Y
>::type
);
};
template <
typename C, typename X, typename Y,
typename First, typename Second
>
struct type_replace_base<C(First, Second), X, Y>
{
typedef typename type_replace<
C, X, Y
>::type type(
typename type_replace<
First, X, Y
>::type,
typename type_replace<
Second, X, Y
>::type
);
};
}
int main()
{
static_assert(std::is_same<
type_replace<int(int, int), int, long>::type,
long(long, long)
>::value, "int should be replaced by long");
return 0;
}
2
Crazy Eddie , . , , , .
, , , , : , , , . , - . Eddy stack , , - .
, stack, , , : typedef T type(Params...);, .
:
template <typename...>
struct stack {};
template <
typename X, typename Y,
typename Stack, typename... Todo
>
struct list_converter;
template <
typename X, typename Y,
typename... Elems
>
struct list_converter<X, Y, stack<Elems...>>
{
typedef stack<Elems...> type;
};
template <
typename X, typename Y,
typename... Elems,
typename First, typename... Todo
>
struct list_converter<X, Y, stack<Elems...>, First, Todo...>
{
typedef typename list_converter<
X, Y,
stack<
typename replace_type<First, X, Y>::type,
Elems...
>,
Todo...
>::type type;
};
template <
typename C, typename X, typename Y,
typename Stack
>
struct function_builder;
template <
typename C, typename X, typename Y,
typename... Elems
>
struct function_builder<C, X, Y, stack<Elems...>>
{
typedef typename replace_type<
C, X, Y
>::type type(Elems...);
};
template <
typename C, typename X, typename Y,
typename... Params
>
struct replace_type<C(Params...), X, Y>
{
typedef typename function_builder<
C, X, Y,
typename list_converter<
X, Y,
stack<>,
Params...
>::type
>::type type;
};
, , ; , .