Есть три числа: 0, 1 и бесконечность.
О, и отсчет начинается с 0, а не с 1!
template<typename... Ts>
struct first_type {}
template<typename T0, typename... Ts>
struct first_type {
typedef T0 type;
};
template<typename... Ts>
using FirstType = typename first_type<Ts...>::type;
template<typename T0, typename Rest, typename=void>
struct foo_impl;
template<typename... Ts>
struct foo_augment {};
template<typename T1>
struct foo_augment<T1> {
T1 m_t1;
T1 t1() const { return m_t1; }
T1 t1() { return m_t1; }
};
template<typename T0, typename... Ts>
struct foo_impl< T0, std::tuple<Ts...>, typename std::enable_if< (sizeof...(Ts)<2) >::type >:
foo_augment<Ts...>
{
// use FirstType<Ts...> to get at the second type of your argument pack
foo_impl( T0 t0, Ts... ts ):
m_t0(t0), foo_augment<Ts...>(ts...)
{};
T0 m_t0;
T0 t0() { return m_t0; }
T0 t0() const { return m_t0; }
};
template<typename T0, typename... Ts>
using foo = foo_impl<T0, std::tuple<Ts...>>;
Теперь обратите внимание, что выше приведено много шаблонного кода, намного больше, чем количество дублированного кода, который вы использовали.
Вместо ...
беспорядка вы можете использовать «зарезервированное значение» для T1
, чтобы указать «не там», например void
. В этом случае вы можете использовать этот трюк с конструктором:
template<typename... Ts, typename=typename std::enable_if< ((sizeof...(Ts)==0) == (std::is_same<T1, void>::value)) && (sizeof...(Ts)<2) >::type >
foo_impl( T0 t0, Ts&&... ts ):
m_t0(t0), foo_augment<Ts...>(std::forward<Ts>(ts)...)
{};
где конструктор является вариарным, но SFINAE означает, что пакет параметров Ts...
должен состоять из 0 элементов, если T1
равен void
, и должен состоять из 1 элемента, если T1
не равен void
.
(Код еще не скомпилирован, но базовый дизайн должен быть здравым).
person
Yakk - Adam Nevraumont
schedule
07.06.2013