Mike Lischke
Mike Lischke

Reputation: 53337

Conditionally define a member variable depending on the existence of the type it is made of

Suppose I have a struct for data:

struct TestData {
}

and a class with a member variable:

class TestContainer {
private:
  TestData data;
};

Both are defined in a cpp file from a macro that is used in multiple test files.

Now I want to remove the data member at compile time if there is no TestData struct defined. If a test doesn't need data then there's no need to define the data member (and it would produce a warning for not being used). I thought of using std::enable_if but failed to come up with a condition. Another approach would be to define a base template class and specializations as shown in this question, but how to specialize on the existence of a type?

How can this be done?

Upvotes: 1

Views: 2819

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41780

You can check if a struct exist or not if you consider a forward declaration is not existing.

This example assume that either TestData is always defined or never defined:

#include <type_traits>

// Comment this line to trigger the static assert
struct TestData {};

template<typename, typename = void>
struct MaybeData {};

template<typename T>
struct MaybeData<T, std::void_t<decltype(sizeof(T))>> {
    T data;
};

struct TestContainer : MaybeData<struct TestData> {};

We can test our solution like this:

template<typename, typename = void>
constexpr auto has_data = false;

template<typename T>
constexpr auto has_data<T, std::void_t<decltype(T::data)>> = true;

static_assert(has_data<TestContainer>);

The mechanism behind this is instead of sending the struct itself (TestData) as a type, we are using struct TestData as an argument, which refers to the type if it exist, but forward declare it if not.

Then, we use sfinae to check if sizeof(T) is a valid expression. If TestData is an imcomplete type, the expression is not valid.

However, if the completeness of a type changes between instantiation of the template, the program is ill formed.

Live example

Upvotes: 3

Related Questions