template <typename T, int I, typename S> struct foo
.foo<foo<void, 1, void>, 1, void>
. The only parameter that takes a foo
struct is the first one typename T
The issue I am having is that for the nested specialization template <foo_t T, int I, typename S> struct foo<T, I, S>
I am not using the template parameter int I
at all.
I would like to have a way to alias "away" that parameter so that I don't have to write that useless parameter for nested foo
variables. I tried two ways but none of them work. I am curious to see if there even is a way to do that cleanly. Can you help me out?
#include <iostream>
template <typename T> concept foo_base_t = requires { typename T::base_tag; };
template <typename T> concept foo_nested_t = requires { typename T::nested_tag; };
template <typename T> concept foo_t = foo_base_t<T> or foo_nested_t<T>;
template <typename T> concept bar_base_t = requires { typename T::base_tag; };
template <typename T> concept bar_nested_t = requires { typename T::nested_tag; };
template <typename T> concept bar_t = bar_base_t<T> or bar_nested_t<T>;
// Version 1 doesn't work
//=============================
template <typename T, int I, typename S>
struct foo
{
using base_tag = void;
};
template <foo_t T, typename S>
struct foo<T, 1, S>
{
using nested_tag = void;
};
//=============================
// Version 2 doesn't work
//=============================
template <typename T, int I, typename S>
struct bar_impl
{
using base_tag = void;
};
template <bar_t T, int I, typename S>
struct bar_impl<T, I, S>
{
using nested_tag = void;
};
template <typename T, int I, typename S>
using bar = bar_impl<T, I, S>;
template <bar_t T, typename S>
using bar<T, S> = bar_impl<T, 1, S>;
//=============================
int main()
{
using T = foo<int, 1, int>;
foo<T, int> o;
using U = bar<int, 1, int>;
bar<U, int> o;
}
I'm a bit unclear about your precise requirements TBH, but is this closer to what you're really trying to do (similar to Jarod42's comment - he beat me to it - but "foo_t" below or similar may be closer to what you're after) ...
#include <type_traits>
#include <iostream>
template <typename T, int I, typename S>
struct foo
{
using base_tag = void;
};
namespace details
{
template <typename T>
struct is_foo_impl : public std::false_type
{
};
template <typename T,
int I,
typename S>
struct is_foo_impl<foo<T, I, S>> : public std::true_type
{
};
}
template <typename T>
concept foo_t = details::is_foo_impl<std::remove_cv_t<T>>::value;
template <foo_t T,
typename S>
using nested_foo = foo<T, 1, S>;
int main()
{
using T = foo<int, 1, int>;
nested_foo<T, int> o;
}