Я следую Как реализовать счетчик константных выражений в С++ Учебник И я пытаюсь исправить С++ 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 мог его найти?