lundi 30 mai 2016

Access template's arguments with partial type knowledge

I have some code with deep C++ 11 variadic template's magic usage. I am using specialized classes to identify parts of template tree, which I am naming "tags". Each tag has unique number identifier. I need to find a way how to access tag's identifiers

Here is some small example:

#include <string>
#include <iostream>

template <unsigned long ID, typename PARAM>
class tag_
{
    //getter for ID. Better to exclude it. If possible - move to external helper
    constexpr static unsigned long get_id() {return ID;}
    //PARAM is used in some functions of this class
};

//tag's declarations for future usage
template<typename PARAM>
using tag1 = tag_<1UL, PARAM>;
template<typename PARAM>
using tag2 = tag_<2UL, PARAM>;
template<typename PARAM>
using tag3 = tag_<3UL, PARAM>;

//helper class that can iterate TAGS
template <template<typename> class... TAGS>
struct helper
{};
template <template<typename> class TAG>
struct helper<TAG>
{
    static void print_tag(std::ostream& out)
    {
        out << std::string("Tag");
        out << TAG::get_id();  // Here I can't call: error: 'template<class> class TAG' used without template parameters
    }
};
template <template<typename> class TAG, template<typename> class... TAGS>
struct helper<TAG, TAGS...>
{
    static void print_tag(std::ostream& out)
    {
        out << std::string("Tag");
        out << TAG::get_id();  // Here I can't call: error: 'template<class> class TAG' used without template parameters
        out << std::string(", ");
        helper<TAGS...>::print_tag(out);
    }
};

//this class uses tags for some processing
template <template<typename> class... TAG_LIST>
class tagged
{
public:
    void test1(std::ostream& out)
    {
        out << std::string("This function works good");
    }
    void test2(std::ostream& out)
    {
        helper<TAG_LIST...>::print_tag(out);
    }
};

// this class is re-defined for some types of T
template<typename T, typename PARAM>
class usage
{
public:
    void test1(std::ostream& out)
    {
        details.test1(out);
    }
    void test2(std::ostream& out)
    {
        details.test2(out);
    }

    T details;
    PARAM params;
};

//endpoint
struct finish{};

//definition for future usage
template<template<typename> class T1, template<typename> class T2, template<typename> class T3, typename PARAM>
using multitag = usage<tagged<T1, T2, T3>, PARAM>;

int main(int argc, const char* argv[])
{
    // this way I am construction my objects tree
    multitag<tag1, tag2, tag3, tag1<tag2<tag3<finish>>>> tmp;
    tmp.test1(std::cout); // ok
    std::cout << std::endl;
    tmp.test2(std::cout);  //compile error. I want to get "Tag1, Tag2, Tag3" printed
    std::cout << std::endl;
}

Aucun commentaire:

Enregistrer un commentaire