Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Определение типов в parameter pack


Автор: Tiarwe 6.9.2014, 03:05
Здравствуйте! Подскажите, как можно пройтись по типам передаваемых в parameter pack.

Код

template<typename... A>
void func(A... a)
{
    const int size = sizeof...(a);

    // тут нужно циклом пройтись в теле которого будет сравнение типов
    // if(typeid(a[1, 2... n]) == typeid(T)) {...}
}

int main()
{
    int a = 1;
    float b = 2.0f;
    bool c = false;

    func(a, b, c);

    return 0;
}

Автор: Tiarwe 6.9.2014, 12:52
Запилил, может кому пригодится:

Код

#include <tuple>
#include <string>

template<typename T>
std::string GetType(T t)
{
    if(typeid(t) == typeid(int))
    {
        return "I";
    }

    if(typeid(t) == typeid(float))
    {
        return "F";
    }

    if(typeid(t) == typeid(bool))
    {
        return "B";
    }

    return "?";
}

template<typename Tuple, std::size_t I>
struct TupleTypes
{
    static std::string Get(const Tuple& tuple)
    {
        std::string lResult;
        lResult += TupleTypes<Tuple, I - 1>::Get(tuple);

        auto lValue = std::get<I>(tuple);
        lResult += GetType(lValue);

        return lResult;
    }
};

template<typename Tuple>
struct TupleTypes<Tuple, 0>
{
    static std::string Get(const Tuple& tuple)
    {
        auto lValue = std::get<0>(tuple);
        std::string& lResult = GetType(lValue);

        return lResult;
    }
};

template<typename Tuple>
std::string GetTupleTypes(const Tuple& tuple)
{
    static const size_t lSize = std::tuple_size<Tuple>::value;
    std::string lResult = TupleTypes<Tuple, lSize - 1>::Get(tuple);

    return lResult;
}

template<typename... A>
std::string GetTypes(A... a)
{
    auto lTuple = std::make_tuple(a...);

    std::string lResult = GetTupleTypes(lTuple);

    return lResult;
}

int main()
{
    std::string lTypes = GetTypes(1, 2.0f, false, "hello");

    return 0;
}

Автор: Lukkoye 6.9.2014, 14:43
Исправил ошибки компиляции, 
Оптимизировал промежуточные вычисления
Удалил лишние копирующие конструкторы
http://rextester.com/HAA37835
Но все равно код ужассен и избыточен.

Код

#include  <iostream>
#include  <typeinfo>
#include  <tuple>
#include  <string>


using namespace std;

template<typename T> std::string GetType(const T& t)
{
    if(typeid(t) == typeid(int))
        return "I";
    if(typeid(t) == typeid(float))
        return "F";
    if(typeid(t) == typeid(bool))
        return "B";
    return "?";
}
template<typename Tuple, std::size_t I> struct TupleTypes
{
    static std::string Get(const Tuple& tuple)
    {
        std::string lResult;
        lResult += TupleTypes<Tuple, I - 1>::Get(tuple);
        auto lValue = std::get<I>(tuple);
        lResult += GetType(lValue);
        return lResult;
    }
};
template<typename Tuple>struct TupleTypes<Tuple, 0>
{
    static std::string Get(const Tuple& tuple)
    {
        const auto lValue = std::get<0>(tuple);
        return GetType(lValue);
    }
};
template<typename Tuple> std::string GetTupleTypes(const Tuple& tuple)
{
    static const size_t lSize = std::tuple_size<Tuple>::value;
    return TupleTypes<Tuple, lSize - 1>::Get(tuple);
}
template<typename... A> std::string GetTypes(A... a)
{
    const auto lTuple = std::make_tuple(a...);
    return GetTupleTypes(lTuple);
}
int main()
{
    std::string lTypes = GetTypes(1, 2.0f, false, "hello");
    cout<<"result = "<<lTypes<<endl;
    return 0;
}


Вот упрощенная версия:
(иллюстрирует технику работы с пакованными аргументами)
http://rextester.com/NELZ86428

Код

#include <typeinfo>
#include <string>
#include <iostream>
using namespace std;

template<class A> ::std::string func(const A& a)
{
    cout<<"type = "<< typeid(a).name()<<endl;
    return typeid(a).name();
}
template<class A, class... Args> ::std::string func(const A& a, const Args&...  args)
{
    cout<<"type = "<< typeid(a).name()<<endl;
    return typeid(a).name() + func(args... );
}

int main()
{
    std::cout << "Hello, world!\n";
    func(0,true);
}


Ответ на вопрос сабжа: работа с variardic template
С учетом дизайна из второго сообщения данной темы
http://rextester.com/DBVNJZ68131


Код

#include <map>
#include <string>
#include <typeinfo>
#include <iostream>
using namespace std;


struct proccessor
{
    typedef ::std::string            str;
    typedef ::std::map<str, str>     mymap;

    template<class A> static str proccess(const A& a)
    {
        cout<<"type = "<< name(typeid(a)) <<endl;
        return name(typeid(a));
    }
    
    template<class A, class... Args> static str proccess(const A& a, const Args&...  args)
    {
        cout<<"type = "<< name(typeid(a)) <<endl;
        return name(typeid(a)) + proccess(args... );
    }
private:
    static const str& unkown()
    {
        static str s="?";
        return s;
    }
    static const str& name(const str& type)
    {
        const auto it = get().find(type);
        if(it==get().end())
            return unkown();
        return it->second;
    }
    static const str& name(const ::std::type_info& i)
    {
        return name( i.name() );
    }
    static bool init(mymap& m)
    {
        m[typeid(int).name()   ] = "int"   ;
        m[typeid(bool).name()  ] = "bool"  ;
        m[typeid(float).name() ] = "float" ;
        return true;
    }
    static mymap& get()
    {
        static mymap m;
        static bool initializer( init(m) );
        return m;
    }
};





int main()
{
    std::cout << "Hello, world!\n";
    
    proccessor::proccess(0,true, "hello");
}


Автор: Tiarwe 7.9.2014, 00:55
Lukkoye, огромное спасибо! Упрощенная версия сильно помогла, набросок пока выглядит так:

Код

#include <typeinfo>
#include <string>
#include <iostream>
using namespace std;

template<typename T>
std::string GetType(T t)
{
    if(typeid(t) == typeid(int))
    {
        return "I";
    }

    if(typeid(t) == typeid(float))
    {
        return "F";
    }

    if(typeid(t) == typeid(bool))
    {
        return "B";
    }

    return "?";
}

template<typename T>
std::string GetTypes(const T& t)
{
    static std::string lResult = GetType(t);

    return lResult;
}

template<typename T, typename... Args>
std::string GetTypes(const T& t, const Args&...  args)
{
    static std::string lResult = GetType(t) + GetTypes(args...);

    return lResult;
}

int main()
{
    std::string lResult1 = GetTypes(0, true, 1.0f, "hello");

    return 0;
}


На функцию std::string GetType(T t) пока не стоит обращать внимания, т.к. она будет переписана со специализациями под нужные типы. Ну а делалось всё это ради вызовов через JNI, для определения сигнатур типов параметров, передаваемых в метод.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)