Информация об изменениях

Сообщение Re[7]: char *(*(**foo[][8])())[]; - за сколько распарсите? от 20.04.2023 23:50

Изменено 21.04.2023 9:18 rg45

Re[7]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, kov_serg, Вы писали:

_>http://coliru.stacked-crooked.com/a/895450c6e1f7529f


ИМХО, ты напрасно завел отдельную специализацию для указателей на функции-члены. И члены-данные, и члены-функции можно обработать общей специализацией указателя на член. Разница только в том, что в одном случае будет тип-объект, а в другом тип-функция. И первое и второе потом распарсится соответствующими специализациями. Подход с общей специализацией формирует более правильное представление о структуре синтаксиса (это ведь учебное упражнение). Да и писанины меньше — и свободные функции, и функции-члены сводятся к одному общему анализатору формальных параметров.

_>А лямбды можно впихать?


Можно, но с ограничением: без auto в параметрах. Тип возвращаемого значения может быть auto. Можно одним движением охватить и ляибды, и std::function, и пользовательские функционалы.

http://coliru.stacked-crooked.com/a/a738b883f4fce75d

#include <iostream>
#include <string>
#include <functional>

template <typename T, typename=void> struct TypeFormatter { std::string operator()() const { return "unknown type"; } };

template <typename...> struct FormatParamList;
template <> struct FormatParamList<> { std::string operator()() const {return {};} };
template <typename A, typename...X> struct FormatParamList<A, X...> { std::string operator()() const { return (TypeFormatter<A>{}() + ... + (", " + TypeFormatter<X>{}()));} };

template <typename> struct FunObjFormatter;
template <typename T, typename C, typename...A> struct FunObjFormatter<T(C::*)(A...)> { std::string operator()() const {return "functional object (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };
template <typename T, typename C, typename...A> struct FunObjFormatter<T(C::*)(A...) const> { std::string operator()() const {return "immutable functional object (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };

template <> struct TypeFormatter<void> { std::string operator()() const { return "void"; } };
template <> struct TypeFormatter<int> { std::string operator()() const { return "int"; } };
template <> struct TypeFormatter<char> { std::string operator()() const { return "char"; } };
template <> struct TypeFormatter<double> { std::string operator()() const { return "double"; } };
template <> struct TypeFormatter<std::string> { std::string operator()() const { return "std::string"; } };
template <typename T> struct TypeFormatter<const T> { std::string operator()() const { return "const " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T*> { std::string operator()() const { return "pointer to " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T&> { std::string operator()() const { return "lvalue refrence to " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T[]> { std::string operator()() const { return "array of unspecified size of " + TypeFormatter<T>()(); } };
template <typename T, size_t N> struct TypeFormatter<T[N]> { std::string operator()() const { return "array [" + std::to_string(N) + "] of " + TypeFormatter<T>()(); } };
template <typename T, typename C> struct TypeFormatter<T C::*> { std::string operator()() const {return "pointer to member of '" + TypeFormatter<C>()() + "' of type: " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T, std::void_t<typename T::TypeFormatter>> : T::TypeFormatter{};
template <typename T, typename...A> struct TypeFormatter<T(A...)> { std::string operator()() const {return "function (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };
template <typename T, typename...A> struct TypeFormatter<T(A...) const> { std::string operator()() const {return "immutable function (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };
template <typename T> struct TypeFormatter<T, std::void_t<decltype(&T::operator())>> : FunObjFormatter<decltype(&T::operator())> {};

namespace NS {
    struct A { };
};
//using NS::A;
//typedef NS::A A;
struct A:NS::A {};

template <> struct TypeFormatter<A> { std::string operator()() const {return "struct A";} };

int main()
{
    std::cout << "01. " << TypeFormatter< char*(*(**[][8])())[] >()() << std::endl;
    std::cout << "02. " << TypeFormatter< int (*)(char,char*(*(**[][8])())[],int) >()() << std::endl;
    std::cout << "03. " << TypeFormatter< int (*)() >()() << std::endl;
    std::cout << "04. " << TypeFormatter< int A::* >()() << std::endl;

    std::cout << "05. " << TypeFormatter<int(const char&, double&)>()() << std::endl;
    std::cout << "06. " << TypeFormatter<int(const char&, double&) const>()() << std::endl;
    std::cout << "07. " << TypeFormatter<int()>()() << std::endl;
    std::cout << "08. " << TypeFormatter<int() const>()() << std::endl;

    auto l1 = []{};
    auto l2 = [](int) { return 3.14; };
    auto l3 = [](int) mutable { return 3.14; };
    auto l4 = [](int, const std::string&, const char*, double) mutable { return 3.14; };

    std::cout << "09. " << TypeFormatter<decltype(l1)>()() << std::endl;
    std::cout << "10. " << TypeFormatter<decltype(l2)>()() << std::endl;
    std::cout << "11. " << TypeFormatter<decltype(l3)>()() << std::endl;
    std::cout << "12. " << TypeFormatter<decltype(l4)>()() << std::endl;

    std::function<double(int, const std::string&, double, const char*)> f1 = std::bind(l3, std::placeholders::_1);

    std::cout << "13. " << TypeFormatter<decltype(f1)>()() << std::endl;
}

01. array of unspecified size of array [8] of pointer to pointer to function () returning pointer to array of unspecified size of pointer to char
02. pointer to function (char, pointer to array [8] of pointer to pointer to function () returning pointer to array of unspecified size of pointer to char, int) returning int
03. pointer to function () returning int
04. pointer to member of 'struct A' of type: int
05. function (lvalue refrence to const char, lvalue refrence to double) returning int
06. immutable function (lvalue refrence to const char, lvalue refrence to double) returning int
07. function () returning int
08. immutable function () returning int
09. immutable functional object () returning void
10. immutable functional object (int) returning double
11. functional object (int) returning double
12. functional object (int, lvalue refrence to const std::string, pointer to const char, double) returning double
13. immutable functional object (int, lvalue refrence to const std::string, double, pointer to const char) returning double
Re[7]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, kov_serg, Вы писали:

_>http://coliru.stacked-crooked.com/a/895450c6e1f7529f


ИМХО, ты напрасно завел отдельную специализацию для указателей на функции-члены. И члены-данные, и члены-функции можно обработать общей специализацией указателя на член. Разница только в том, что в одном случае будет тип-объект, а в другом тип-функция. И первое и второе потом распарсится соответствующими специализациями. Подход с общей специализацией формирует более правильное представление о структуре синтаксиса (это ведь учебное упражнение). Да и писанины меньше — и свободные функции, и функции-члены сводятся к одному общему анализатору.

_>А лямбды можно впихать?


Можно, но с ограничением: без auto в параметрах. Тип возвращаемого значения может быть auto. Можно одним движением охватить и ляибды, и std::function, и пользовательские функционалы.

http://coliru.stacked-crooked.com/a/a738b883f4fce75d

#include <iostream>
#include <string>
#include <functional>

template <typename T, typename=void> struct TypeFormatter { std::string operator()() const { return "unknown type"; } };

template <typename...> struct FormatParamList;
template <> struct FormatParamList<> { std::string operator()() const {return {};} };
template <typename A, typename...X> struct FormatParamList<A, X...> { std::string operator()() const { return (TypeFormatter<A>{}() + ... + (", " + TypeFormatter<X>{}()));} };

template <typename> struct FunObjFormatter;
template <typename T, typename C, typename...A> struct FunObjFormatter<T(C::*)(A...)> { std::string operator()() const {return "functional object (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };
template <typename T, typename C, typename...A> struct FunObjFormatter<T(C::*)(A...) const> { std::string operator()() const {return "immutable functional object (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };

template <> struct TypeFormatter<void> { std::string operator()() const { return "void"; } };
template <> struct TypeFormatter<int> { std::string operator()() const { return "int"; } };
template <> struct TypeFormatter<char> { std::string operator()() const { return "char"; } };
template <> struct TypeFormatter<double> { std::string operator()() const { return "double"; } };
template <> struct TypeFormatter<std::string> { std::string operator()() const { return "std::string"; } };
template <typename T> struct TypeFormatter<const T> { std::string operator()() const { return "const " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T*> { std::string operator()() const { return "pointer to " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T&> { std::string operator()() const { return "lvalue refrence to " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T[]> { std::string operator()() const { return "array of unspecified size of " + TypeFormatter<T>()(); } };
template <typename T, size_t N> struct TypeFormatter<T[N]> { std::string operator()() const { return "array [" + std::to_string(N) + "] of " + TypeFormatter<T>()(); } };
template <typename T, typename C> struct TypeFormatter<T C::*> { std::string operator()() const {return "pointer to member of '" + TypeFormatter<C>()() + "' of type: " + TypeFormatter<T>()(); } };
template <typename T> struct TypeFormatter<T, std::void_t<typename T::TypeFormatter>> : T::TypeFormatter{};
template <typename T, typename...A> struct TypeFormatter<T(A...)> { std::string operator()() const {return "function (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };
template <typename T, typename...A> struct TypeFormatter<T(A...) const> { std::string operator()() const {return "immutable function (" + FormatParamList<A...>{}() + ") returning " + TypeFormatter<T>{}();} };
template <typename T> struct TypeFormatter<T, std::void_t<decltype(&T::operator())>> : FunObjFormatter<decltype(&T::operator())> {};

namespace NS {
    struct A { };
};
//using NS::A;
//typedef NS::A A;
struct A:NS::A {};

template <> struct TypeFormatter<A> { std::string operator()() const {return "struct A";} };

int main()
{
    std::cout << "01. " << TypeFormatter< char*(*(**[][8])())[] >()() << std::endl;
    std::cout << "02. " << TypeFormatter< int (*)(char,char*(*(**[][8])())[],int) >()() << std::endl;
    std::cout << "03. " << TypeFormatter< int (*)() >()() << std::endl;
    std::cout << "04. " << TypeFormatter< int A::* >()() << std::endl;

    std::cout << "05. " << TypeFormatter<int(const char&, double&)>()() << std::endl;
    std::cout << "06. " << TypeFormatter<int(const char&, double&) const>()() << std::endl;
    std::cout << "07. " << TypeFormatter<int()>()() << std::endl;
    std::cout << "08. " << TypeFormatter<int() const>()() << std::endl;

    auto l1 = []{};
    auto l2 = [](int) { return 3.14; };
    auto l3 = [](int) mutable { return 3.14; };
    auto l4 = [](int, const std::string&, const char*, double) mutable { return 3.14; };

    std::cout << "09. " << TypeFormatter<decltype(l1)>()() << std::endl;
    std::cout << "10. " << TypeFormatter<decltype(l2)>()() << std::endl;
    std::cout << "11. " << TypeFormatter<decltype(l3)>()() << std::endl;
    std::cout << "12. " << TypeFormatter<decltype(l4)>()() << std::endl;

    std::function<double(int, const std::string&, double, const char*)> f1 = std::bind(l3, std::placeholders::_1);

    std::cout << "13. " << TypeFormatter<decltype(f1)>()() << std::endl;
}

01. array of unspecified size of array [8] of pointer to pointer to function () returning pointer to array of unspecified size of pointer to char
02. pointer to function (char, pointer to array [8] of pointer to pointer to function () returning pointer to array of unspecified size of pointer to char, int) returning int
03. pointer to function () returning int
04. pointer to member of 'struct A' of type: int
05. function (lvalue refrence to const char, lvalue refrence to double) returning int
06. immutable function (lvalue refrence to const char, lvalue refrence to double) returning int
07. function () returning int
08. immutable function () returning int
09. immutable functional object () returning void
10. immutable functional object (int) returning double
11. functional object (int) returning double
12. functional object (int, lvalue refrence to const std::string, pointer to const char, double) returning double
13. immutable functional object (int, lvalue refrence to const std::string, double, pointer to const char) returning double