Вариативный класс шаблона, содержащий массив другого класса шаблона

Я создаю свою собственную СУБД для практики C++. Я придумал решение, в котором каждый столбец может иметь тип и является шаблоном. Вот так выглядит строка, но она не работает

template <typename... col_types>
struct row {
  row(std::tuple<std::function<bool(col_types)>, bool, col_types>...col_data){
    int i = 0;
    ([&]{
        columns[i] = std::make_unique<column_impl<decltype(std::get<2>(col_data))>>(std::get<0>(col_data), std::get<1>(col_data), std::get<2>(col_data));
        i++;
    }(), ...);
  }
  std::array<std::unique_ptr<column_impl<col_types>>, sizeof...(col_types)> columns;
};

А вот column_impl

template <typename data_t>
struct column_impl {
  column_impl<data_t>() {}
  column_impl<data_t>(std::function<bool(data_t)> _constraint) : constraint(_constraint) {}
  column_impl<data_t>(std::function<bool(data_t)> _constraint, bool _is_nullable)
      : constraint(_constraint), is_nullable(_is_nullable) {}

  // This constructor requires to validate whether provided data
  // satisfies provided constraint. If constraint isn't satisfied
  // an exception gets thrown. It needs to be handled
  column_impl<data_t>(std::function<bool(data_t)> _constraint, bool _is_nullable, data_t _value)
      : constraint(_constraint), is_nullable(_is_nullable) {
    if (validate_data()) {
      value = _value;
    } else {
      throw std::invalid_argument("Provived data couldn't satisfy column's constraint");
    }
  }

  std::function<bool(data_t)> constraint = [](data_t) { return true; };
  bool is_nullable = false;
  data_t value;
  auto get_column_type_variant() { return std::variant<data_t>(); }

  bool validate_data() { return constraint(value); }

  template <typename T>
  bool validate_type(T) {
    return std::is_nothrow_convertible<T, data_t>();
  }
};

Любые идеи, как создать контейнер для столбцов внутри строки и создать конструктор, который распаковывает кортежи в строку? Я не могу заставить его работать. Я знаю, что этот массив не должен работать, но я понятия не имею, как его лучше написать. А еще я не хочу вектор. Я мог бы написать полиморфную оболочку вроде struct column{some_type_containing_column_impls column_obj;}, но я понятия не имею, как это сделать. И как правильно распаковать эти кортежи в объект column_impl?

Мне кажется, вы пытаетесь создать std::array, где каждое значение относится к другому типу? К сожалению, C++ так не работает. Вам нужно будет найти какой-то другой подход. Возможно, подход на основе std::tuple.

Sam Varshavchik 18.02.2023 14:08

Да, как я уже сказал, это не правильный подход. Но я не могу думать ни о чем другом, и мне нужна помощь.

k1t3k 18.02.2023 14:09

Как я уже сказал, подход на основе кортежей должен работать. Но это будет работать совершенно по-другому.

Sam Varshavchik 18.02.2023 16:06
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Ускорьте разработку веб-приложений Laravel с помощью этих бесплатных стартовых наборов
Laravel - это мощный PHP-фреймворк, используемый для создания масштабируемых и надежных веб-приложений. Одним из преимуществ Laravel является его...
Что такое двойные вопросительные знаки (??) в JavaScript?
Что такое двойные вопросительные знаки (??) в JavaScript?
Как безопасно обрабатывать неопределенные и нулевые значения в коде с помощью Nullish Coalescing
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание ресурсов API Laravel: Советы по производительности и масштабируемости
Создание API-ресурса Laravel может быть непростой задачей. Она требует глубокого понимания возможностей Laravel и лучших практик, чтобы обеспечить...
Как сделать компонент справочного центра с помощью TailwindCSS
Как сделать компонент справочного центра с помощью TailwindCSS
Справочный центр - это веб-сайт, где клиенты могут найти ответы на свои вопросы и решения своих проблем. Созданный для решения многих распространенных...
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
0
3
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Использование только аргументов шаблона, не являющихся типом, может сделать это.

template<class T>
bool default_constraint(T) {
    return true;
}

template<class T, bool nullable = true, bool(constraint)(T) = default_constraint>
class column {
    T data;
    bool is_null;
public:
    column() : data(), is_null(true) { ///< T must be DefaultConstructable
        if (!validate())
            throw std::invalid_argument("Provided data couldn't satisfy column's constraint");
    }

    column(T data) : data(data), is_null(false) {
        if (!validate())
            throw std::invalid_argument("Provided data couldn't satisfy column's constraint");
    }

    bool validate() {
        return nullable || is_null || constraint(data);
    }

    T get() {
        return data;
    }
};

template<class... C>
struct row {
    std::tuple<C...> columns;

    row(C&&... c) : columns(std::forward<C>(c)...) {}

    template<int index>
    auto get() {
        return std::get<index>(columns).get();
    }
};

bool require_positive(int i) {
    return i >= 0;
}

int main() {
    typedef row<column<int>, column<float>, column<bool>> MyRow;
    MyRow r{1, 2.3f, true};

    using MyRow2 = row<column<int, false, require_positive>, column<float>>;
    MyRow2 r2{-1, 2.5}; ///< exception thrown
}

Я знаю, может быть, вам нужна только «идея» того, как реализовать, но я просто публикую код здесь для ясности.

Другие вопросы по теме