Some of your metaprogramming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log max
) rather than O(max
).
Some of your metaprogramming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log max
) rather than O(max
).
Some of your metaprogramming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log max
) rather than O(max
).
Some of your meta-programmingmetaprogramming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log \$O(log(max))\$max
) rather than \$O(max)\$O(max
).
Some of your meta-programming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is \$O(log(max))\$ rather than \$O(max)\$.
Some of your metaprogramming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log max
) rather than O(max
).
Some of your metaprogrammingmeta-programming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log max
)\$O(log(max))\$ rather than O(max
)\$O(max)\$.
Some of your metaprogramming machinery is a bit over-complicated for C++11. Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is O(log max
) rather than O(max
).
Some of your meta-programming machinery is a bit over-complicated for C++11.
Compare:
template <size_t... n>
struct ct_integers_list {
template <size_t m>
struct push_back
{
typedef ct_integers_list<n..., m> type;
};
};
template <size_t max>
struct ct_iota_1
{
typedef typename ct_iota_1<max-1>::type::template push_back<max>::type type;
};
template <>
struct ct_iota_1<0>
{
typedef ct_integers_list<> type;
};
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
increment(std::tuple<Tp...>& t)
{ }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<(I < sizeof...(Tp)), void>::type
increment(std::tuple<Tp...>& t)
{
std::get<I>(t)++ ;
increment<I + 1, Tp...>(t);
}
Versus:
template<size_t... n> struct ct_integers_list {};
template<size_t... acc> struct ct_iota_1;
template<size_t max, size_t... acc> struct ct_iota_1 : ct_iota_1<max-1, max-1, acc...> {};
template<size_t... acc> struct ct_iota_1<0, acc...> : ct_integers_list<acc...> {};
template<size_t... Indices, typename Tuple>
inline void increment_helper(Tuple& t, ct_integers_list<Indices...>)
{
std::initializer_list<int>{
[&]{ ++std::get<Indices>(t); return 0; }()...
};
}
template<typename... Tp>
inline void increment(std::tuple<Tp...>& t)
{
increment_helper(t, ct_iota_1<sizeof...(Tp)>());
}
The idea is to let parameter-pack expansion do for you all the things that in C++03 you had to do via foo<T>::type
typedefs and std::enable_if
and so on.
Basically, you can replace a lot of recursion with iteration (as in my increment_helper
); and for the stuff that has to remain recursion, you can make it look a bit neater and avoid the proliferation of entities (à la Occam's Razor). If you don't need all those intermediate ct_iota_1<...>::type
entities, get rid of them!
However, if you want a production-quality ct_integers_list
, you should be using C++14's predefined std::integer_sequence
, or at least an efficient implementation such as this one by Xeo. Compilers often limit template recursion to something like 256 levels; both your version and mine will quickly run into this limit, whereas Xeo's will work fine, because its recursion is \$O(log(max))\$ rather than \$O(max)\$.
- 19.7k
- 2
- 44
- 91