私のソリューション:))のgcc 4.6.4 -std = C++ 0xの
主なアイデアは、任意の 'I' と0,1,2、... N-ため、あるとコンパイル((n-1)^ i) - は一意のシーケンスであり、値'i'の位置はゼロです。
O(1)溶液、O(log(n))溶液ではありません。しかし、それはC++ 14 make_index_sequenceに基づいています。 IffコンパイラはO(1)でmake_index_sequenceをコンパイルするので、私の解決法もO(1)になりました。
#include <cstddef>
#include <iostream>
#include <type_traits>
namespace mpl
{
// C++14 index_sequence struct
template< int ... i >
struct index_sequence
{
typedef index_sequence type;
typedef int value_type;
static constexpr std::size_t size()noexcept{ return sizeof...(i); }
};
namespace details
{
#if 1
template< int s, typename T, typename U> struct concate_c;
template<int s, int ...i, int ...j>
struct concate_c< s, index_sequence<i...>, index_sequence<j...> >
: index_sequence<i..., (j + s) ... > {};
template< int s, typename T, typename U> struct concate : concate_c< s, typename T::type, typename U::type > {};
template< int n>
struct make_index_sequence : concate< n/2,
make_index_sequence<n/2>,
make_index_sequence< n - n/2 >
>{};
#else
template< typename T, typename U> struct concate_c;
template< int ...i, int ...j>
struct concate_c< index_sequence<i...>, index_sequence<j...> >
: index_sequence<i..., (j + sizeof...(i)) ... > {};
template< typename T, typename U> struct concate : concate_c< typename T::type, typename U::type > {};
template< int n>
struct make_index_sequence : concate<
make_index_sequence<n/2>,
make_index_sequence< n - n/2 >
>{};
#endif
template<> struct make_index_sequence<0> : index_sequence<>{};
template<> struct make_index_sequence<1> : index_sequence<0>{};
} // namespace details
template< int n> struct make_index_sequence : details::make_index_sequence<n> {};
template< typename ...Args>
struct make_index_sequence_for : make_index_sequence< sizeof...(Args) > {};
// helper for at_c, I - index_sequence,
template< typename I, typename ...p >
struct at_ch;
// only zero index have `type`.
template< int i, typename T> struct id{};
template< typename T>struct id<0,T>{ typedef T type;};
// based from all parameters.
template< typename ...T> struct base_all : T... {};
template< int ... i, typename ...p>
struct at_ch< index_sequence<i...>, p... >
{
struct base : base_all< id<i,p> ... > {};
typedef typename base::type type;
};
// 0 1 2 3 4 5 6 7 8 9
// 0: 0 1 2 3 4 5 6 7 8 9
// 1: 1 0 3 2 5 4 7 6 9 8
template< int i, typename I>
struct xor_index_sequence;
template< int i, int ...k>
struct xor_index_sequence< i, index_sequence<k...> > : index_sequence< (k xor i) ... > {};
template< int i, typename ...T>
struct at_c: at_ch<
typename xor_index_sequence< i,
typename make_index_sequence< sizeof...(T)> ::type
>::type,
T...
> {};
}
int main()
{
typedef mpl::at_c< 2, int, double , float >::type G;
static_assert(std::is_same<G, float>::value ,"!");
return 0;
}
手動で1,2,3,4,6、...の最初のパラメータとものを持つ無限の量の過負荷を提供することができます。それ以外に、あなたが得ることができる最高のものは 'log N'です。 – Xeo
@ Xeo十分に速く成長する再帰を使って 'ログログN 'を取り除くことができるはずですか?非常に無意味ですが、 'log N'の下では1000回の再帰制限が無限に遠くにあり、' log log N'再帰深度を取り除くオーバーヘッドは、合理的に 'N'の差よりも大きくなります... – Yakk
そのような 'static_cast'を使用します。私たちは理由のために['std :: forward'](http://en.cppreference.com/w/cpp/utility/forward)を持っています。それははるかに読みやすく、実際にあなたがそれをやっている理由を読者に伝えています'static_cast'とは異なり、秘密ではなく、知らない人にとって意味のないものです。 –