これが私の小さな貢献です。
まず、存在メソッドから始めます。
template <unsigned>
static unsigned char exists_impl(...);
template <unsigned N, typename T>
static auto exists_impl(T const&&) ->
typename std::enable_if<sizeof(typename T::template D<N>),
unsigned char (&)[2]>::type;
template <typename T, unsigned N>
static constexpr bool exists() {
return sizeof(exists_impl<N>(std::declval<T>())) != 1;
}
ここでは、関数の使用法が読みやすさの点でテーブルに多くをもたらすと信じているconstexpr
ので、私は典型的なタイプを使用しません。
次に、読みやすさを損なう典型的な二分探索(2回目の試行、下部の最初の試行を参照)を使用しますが、遅延インスタンス化の恩恵を受けるために、部分的なテンプレートの特殊化を使用しますstd::conditional
。
template <typename T, unsigned low, unsigned high, typename = void>
struct highest_index_in;
template <typename T, unsigned low>
struct highest_index_in<T, low, low>: std::integral_constant<unsigned, low> {};
template <typename T, unsigned low, unsigned high>
struct highest_index_in<T, low, high, typename std::enable_if<(high == low + 1)>::type>:
std::integral_constant<unsigned, low + exists<T, low+1>()> {};
template <typename T, unsigned low, unsigned high>
struct highest_index_in<T, low, high, typename std::enable_if<(high > low + 1)>::type>:
std::conditional< exists<T, (low+high)/2>(),
highest_index_in<T, (low+high)/2, high>,
highest_index_in<T, low, (low+high)/2> >::type
{};
template <typename T>
static constexpr unsigned highest_index() {
return highest_index_in<T, 0, ~(0u)>::value;
} // highest_index
ライブワークスペースでのデモ、コンピューティングhighest_index<C>()
はほぼ瞬時に行われます。
バイナリ検索の最初の試みですが、残念ながら、コンパイラは関数本体を再帰的にインスタンス化する必要があり(インスタンス化できることを証明するため)、したがって、実行する必要のある作業は膨大です。
template <typename T, unsigned low, unsigned high>
static constexpr auto highest_index_in() ->
typename std::enable_if<high >= low, unsigned>::type
{
return low == high ? low :
high == low + 1 ? (exists<T, high>() ? high : low) :
exists<T, (high + low)/2>() ? highest_index_in<T, (high+low)/2, high>() :
highest_index_in<T, low, (high+low)/2>();
} // highest_index_in
template <typename T>
static constexpr unsigned highest_index() {
return highest_index_in<T, 0, ~(0u)>();
} // highest_index
そのため、残念ながら、highest_index
使用できず、clangの動作が遅くなります(gccのパフォーマンスが向上しているようには見えません)。