Search code examples
c++templatestemplate-meta-programmingboost-mpl

Generating C++ typename by concatenating template parameter with a string


I'm trying to figure out a way to use Boost::MPL to generate a typename which is the concatenation of a template parameter and a string.

I have pairs of classes which are named: X and XProvider. The latter is a factory class which instantiates objects inherited from the former type.

The template class is intended to manage the instantiation of types at runtime: it contains, among other things, an unordered_map and some other misc. members.

What I am ultimately trying to achieve is a metafunction that looks something like this:

Given the class

template <typename T>
class Plugin_Manager{

    using Base_Type = T;

    std::vector<Get_Provider_Type<Base_Type>::type *> m_provider_collection;

      */ ... /*

};

Where Get_Provider_Type<T> is a metafunction which returns a typename TProvider.

Based on this answer, I think that the metafunction should look something along the lines of this:

    template < typename Str1, typename Str2 >
    struct concat : boost::mpl::insert_range < Str1, typename boost::mpl::end<Str1>::type, Str2 > {};


    template <class T> struct Get_Provider_Type{
        typedef typename boost::mpl::string<boost::mpl::c_str<T>::value>::type Base_Name;
        typedef boost::mpl::string<'Prov', 'ider'> Suffix;

        typedef typename concat<Base_Name, Suffix>::type type;
    };

However, I am really not understanding mpl::c_str or mpl::string or their correct usage, and I cannot follow the error messages that I am receiving. The code as written above gives me the error message:

    error C2039: 'value_type' : is not a member of 'foo'

(foo here being the template argument -- Plugin_Manager<foo>)

I realize that I can likely make this work if I use a large macro rather than c++ template, but I would really like to avoid that if at all possible.

I'd really appreciate any suggestions.

Thanks- Shmuel


Solution

  • Well, you can't get a typename from concatenating strings with template parameters, but if your intention is...

    I'd like to have a metafunction Get_Provider_Type::type which will return for me the type fooProvider

    You can simply define the type in foo:

    struct foo {
        using provider = fooProvider;
    };
    

    If you need it, you can implement your "metafunction" that will work with all types that define T::provider

    template<class T>
    struct Get_Provider_Type {
        using type = typename T::provider;
    };
    

    Which can be useful if you can't modify foo to define the type. Then you can specialize Get_Provider_Type instead:

    template<>
    struct Get_Provider_Type<foo> {
        using type = fooProvider;
    };