Я следую Как реализовать счетчик константных выражений в С++ Учебник И я пытаюсь исправить С++ 14 Размышления без макросов, разметки и внешнего инструментария. Ограничения.
Основная идея учебника такова:
template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
};
template<int N>
struct writer {
friend constexpr int adl_flag (flag<N>) { return N; }
static constexpr int value = N;
};
template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }
template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }
int constexpr reader (float, flag<0>) { return 0; }
template<int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<C + N>::value) { return R; }
int main () {
constexpr int a = next ();
constexpr int b = next ();
constexpr int c = next ();
// YES! it works!!!
static_assert (a == 1 && b == a+1 && c == b+1, "try again");
}
Примечание. Если вас сейчас не интересует, то пора прекратить чтение: -)
В обсуждении объясняется, как извлекать количество полей и типов полей для типов POD с использованием агрегатной инициализации и оператора неявного преобразования, но основное ограничение заключается в том, что поддерживаются только примитивные типы.
Я предоставил вышеуказанный фон, чтобы оправдать мои мотивы!
Когда я объединил эти два подхода, я пришел к следующему:
template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
};
template<typename T, int N>
struct writer {
friend constexpr int adl_flag (flag<N>) {
return N;
}
friend constexpr T field_type(flag<N>) { return T{}; }
static constexpr int value = N;
};
field_type(flag<N>)
даст мне тип N
-го поля.
Обратите внимание, что это функция друга и для N
-го поля типа POD
точно один field_type(flag<N>)
будет определен компилятором.
g++
дает no matching function for call to 'field_type(flag<1>)
для decltype(field_type(flag<1>))
.
Мне нужно как-то заставить ADL
искать во всех экземплярах writer<T,N>
.
Как я могу это сделать?
Обновление
Как @T.C.mentioned ADL рассматривает только связанные классы, а writer
не является одним. (Вот почему adl_flag
объявлен в flag
- так, чтобы ADL
мог его найти.)
Весь вопрос заключается в том, как сделать writer
связанный класс без знания значения T
, чтобы ADL
мог его найти?