Могу ли я заставить пользователя предоставить значение для члена при использовании назначенных инициализаторов? - PullRequest
0 голосов
/ 02 ноября 2019

Я создал структуру параметров, предназначенную для использования через назначенный инициализатор:

struct FooOptions {
    bool enableReticulation;
};

void Foo(FooOptions&& opts);

Foo(FooOptions{.enableReticulation = true});

К сожалению, поскольку bool имеет конструктор по умолчанию, его также можно сделать следующим образом:

Foo(FooOptions{});

но я не хочу этого;Я хочу, чтобы пользователи Foo явно решили включить сетку или нет. Я могу добиться этого с помощью ошибки времени выполнения следующим образом:

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

Но я бы предпочел сделать это с ошибкой времени компиляции. Есть ли способ сделать это? Я согласен с изменением bool на SomeWrapper<bool> при необходимости, пока я могу в основном инициализировать SomeWrapper<T>, как если бы это был T, но без инициализатора по умолчанию.

Ответы [ 2 ]

2 голосов
/ 02 ноября 2019

Вы пояснили, что речь идет о произвольных классах, а не о примитивных типах. Для произвольных классов с произвольными конструкторами: просто удалите конструктор, но явно delete конструктор по умолчанию:

template<typename T> class SomeWrapper : public T {

    SomeWrapper()=delete;

    using T::T;
};

Тогда:

#include <vector>

foo F{ {1,2} }; // Works, initializes the vector with {1,2}

foo G{}; // Fails

Это может работать не так, как вы хотите дляпримитивные типы. Просто специализируйте SomeWrapper по мере необходимости. Примитивных типов не так много, чтобы иметь дело.

1 голос
/ 02 ноября 2019

Способ обработки классов и типов, не относящихся к классам, благодаря 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; }
};

Демо

...