Search code examples
c++initializationdesignated-initializer

Can I force a user to provide a value for a member when using designated initializers?


I have created an options struct, intended to be used via designated initializer:

struct FooOptions {
    bool enableReticulation;
};

void Foo(FooOptions&& opts);

Foo(FooOptions{.enableReticulation = true});

Unfortunately, because bool has a default constructor, it's also valid to do this:

Foo(FooOptions{});

but I don't want this; I want users of Foo to explicitly decide to enable reticulation or not. I can achieve this with a runtime error this way:

struct FooOptions {
    bool enableReticulation = []() -> bool { 
        assert(false, "No value provided for enableReticulation");
    }();
};

But I would prefer to do this with a compile time error. Is there any way to do that? I am OK with changing bool to SomeWrapper<bool> if necessary, as long I can mostly initialize SomeWrapper<T> as if it were T, but without a default initializer.


Solution

  • Way to handle classes and non-classes types, thank to SFINAE:

    template<typename T, typename Enabler = void> class TWrapper;
    
    template<typename T>
    class TWrapper<T, std::enable_if_t<std::is_class<T>::value>> : public T {
    public:
        TWrapper()=delete;
    
        using T::T;
    };
    
    template<typename T>
    class TWrapper<T, std::enable_if_t<!std::is_class<T>::value>>
    {
    public:
        TWrapper()=delete;
    
        T value;
        TWrapper(T arg) : value(arg) {}
        operator T() const { return value; }
    };
    

    Demo