0

Here is a sample code to clarify what I want to achieve:

template<typename T>
struct Compose{
    T some_way_to_make_name_out_of_type(T);
// -------------------^
// It may be some preprocessor hack or something based on templates
};

The reason I want to do this is that there is a way to check if the field of a certain type exists in the class. So I want to unify the names.

The only limitations are

  • the name must be unique with respect to type.
  • It is preferred not to use external code generation tools like Cog (Boost is OK though)

My goal is to make the way to generalize approach from the code above and make the same Compose structure, but for any number of types:

template <typename ... ComponentsTypes>
struct Compose {
//....
};


using Compose<int, float, std::string> = ifsType;

ifsType ifs{};

ifs.int_field = 3;
ifs.float_field = 4.0;
ifs.std_string_filed = "hi";

Let's assume that it is never desired to compose two components of the same type.

using Compose<int, int> = iiType; // <-- will not compile
FrogOfJuly
  • 125
  • 3
  • 2
    How about using `std::tuple`, and use something like `ifs.get() = 3;` or `get(ifs.data) = 3;`? detecting if tuple contains type is as easy than detecting member. – Jarod42 Apr 19 '21 at 08:45
  • Looks like you want `std::tuple` – super Apr 19 '21 at 08:46
  • If you really want member names based on templates, it is not possible. Someone suggested a way to achieve it using the preprocessor here. https://stackoverflow.com/questions/33099226/c-generic-template-method-name-from-template-parameter – Mihail Feraru Apr 19 '21 at 08:48
  • Hmm, maybe I want tuples. @Jarod42, though I heard that they are not very nice to use. If no better way will come up I think your comment is close to answering to my question. – FrogOfJuly Apr 19 '21 at 08:55
  • @MihailFeraru, variadic macroses are a good idea actually. – FrogOfJuly Apr 19 '21 at 09:01
  • "Nice to use" is a very use case specific thing. Depends on what are you trying to achieve. – Mihail Feraru Apr 19 '21 at 09:05

1 Answers1

0

You cannot generate member name from template parameter. You can play with MACRO, something like:

#define DEFINE_COMPOSE(type) \
  struct Compose_ ## type { \
      T T ## _field; \
  }

DEFINE_COMPOSE(int);

Compose_int ifs;
ifs.int_field = 3;

Variadic Macro can be used to handle up-to some hard count limit.

In regular C++, std::tuple seems enough:

template <typename ... Ts>
struct Compose
{
    std::tuple<Ts...> data;

    template <typename T>
    T& get() { return std::get<T>(data); }

    template <typename T>
    const T& get() const { return std::get<T>(data); }

    // Code to detect if T is in Ts...
    template <typename T>
    static constexpr bool has_type() { return (std::is_same_v<T, Ts> || ...); }
};

// With possible usage:
void foo()
{
    Compose<int, float, std::string> ifs;
    
    ifs.get<int>() = 3;
    std::get<int>(ifs.data) = 3;

    static_assert(Compose<int, float, std::string>::has_type<float>());
    static_assert(!Compose<int, float, std::string>::has_type<char>());
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302