Можно ли ссылаться на аргументы шаблона шаблона?

Я экспериментирую с шаблонами на C++, реализуя библиотеку линейной алгебры, поэтому этот пример может не подойти для этой работы лучше всего.

Допустим, у меня есть N-мерный контейнер, который содержит данные и общие функции векторов и матриц, от которых я хочу наследовать (я знаю, что общепринятой практикой является определение типа матрицы, а затем использование объявления using для различных линейных алгебр. типы, как в собственном, но я хочу наследовать этот контейнер, а затем добавлять методы к различным типам. Опять же, это может быть не лучшим вариантом, но это эксперимент).

template <typename T, std::size_t... Dims>
class NDimContainer {
public:
    auto operator+=(const NDimContainer &other) {
        std::transform(elems.begin(), elems.end(), other.begin(), std::plus<T>());
        return *this;
    }
private:
    std::array<T, (... * Dims)> elems;
};

template <typename T, std::size_t Dims>
class Vector : public NDimContainer<T, Dims> { ... }

Вопрос в следующем: можно ли получить доступ к аргументам шаблона N и Dims..., указанным в шаблоне шаблона, следующим образом:

template <template<typename N, std::size_t... Dims> typename T>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { 
    return T { lhs } += rhs;
}

Я знаю, что это возможно сделать:

template <template<typename, std::size_t...> typename T, typename N, std::size_t... Dims>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { ... }

Но тогда шаблон не будет сопоставлен, например. Vector напечатайте (по крайней мере, в моем случае это не так, если это какая-то банальная ошибка, пожалуйста, поправьте меня).

Есть ли способ заставить эту работу работать так, чтобы я мог сделать что-то подобное?

Vector<int, 3> a = Vector<int, 3>() + Vector<int, 3>();

Предыдущие вопросы по этой теме я нашел здесь и здесь. Но ни один из них на самом деле не решает мой вариант использования.

Виновником, который запрещает гораздо более простое решение, является Dims..., потому что я не знаю, как сделать что-то вроде этого:

template <typename T, std::size_t... Dims>
class A {
public:
    using Type = T;
    using Dimensions = Dims...; // Error
};

Вероятно, можно было бы использовать std::integer_sequence, но это потребует дополнительных затрат на пространство, которые я не хочу платить.

Я пробовал что-то вроде этого:

template <template<typename N, std::size_t... Dims> typename T, typename NN = N, std::size_t... DDims = Dims>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { ... }

Но это, очевидно, тоже не сработало.

Возможна ли подобная конструкция?

изменить: добавление минимального воспроизводимого примера

#include <array>
#include <concepts>

template<typename T, std::size_t ... Dims>
struct A {
    std::array<T,(Dims*...)> data = {};
    A& operator+=( const A& ) noexcept;
};

// This is the one I would like it matched instead, because then it would be instantiated for
// particular type.
template<template<typename N, std::size_t... Dims> typename T>
requires std::derived_from<A<N, Dims...>, T<N, Dims...>>
auto operator+(const A<N, Dims...>& lhs, const A<N, Dims...>& rhs) -> A<N, Dims...> {
    return A{lhs} += rhs;
}

template<typename T, std::size_t N>
struct Vector : A<T,N> {
    using Base = A<T,N>;

    Vector() = default;
    Vector(const Base& base) : Base(base) {}
};

using Vector3d = Vector<double,3>;

int main() {
    Vector3d vec = Vector3d{} + Vector3d{};

    return 0;
}

«Можно ли получить доступ к аргументам шаблона N и Dims...» Нет.

user12002570 07.08.2024 11:58

Также составьте минимальный воспроизводимый пример со всеми #includes

user12002570 07.08.2024 12:05

«Наверное, можно было бы использовать std::integer_sequence, но это потребует дополнительных затрат места» — using Dimensions = std::integer_sequence<Dims...>; не занимает места

Ted Lyngmo 07.08.2024 12:23

Я привел минимальный воспроизводимый пример, но это был скорее теоретический вопрос. @TedLyngmo, честно говоря, я еще не закончил с этим, и это может даже решить мою проблему, отличная идея, я был зациклен на идее сохранить последовательность в переменной.

Daniel Kříž 07.08.2024 12:28

Всегда публикуйте полную ошибку вместе с вашим вопросом. Сейчас в коде много ошибок. По сути, опубликуйте минимальный воспроизводимый пример, который воспроизводит указанную ошибку, вместо публикации кода, который компилируется. Я пытаюсь исправить ошибки в коде, но кажется, что глупых ошибок слишком много. Как будто в C++ нет is_derived_from, вместо этого должно быть derived_from

user12002570 07.08.2024 12:36

Хорошо, я изменил пример, чтобы он выглядел именно так, как я себе представлял, как может выглядеть код. Но опять же, у меня нет проблем с конкретным фрагментом кода. Мне было интересно, можно ли ссылаться на аргументы шаблона N и Dims.

Daniel Kříž 07.08.2024 13:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ваш вопрос слишком длинный и в нем слишком много вопросов. Я сосредоточусь на этом:

Вопрос в следующем: можно ли получить доступ к аргументам шаблона N и Dims..., указанным в шаблоне шаблона, следующим образом:

template <template<typename N, std::size_t... Dims> typename T>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { 
    return T { lhs } += rhs;
}

Нет. Здесь template <template<typename N, std::size_t... Dims> typename T> вы говорите, что T — это шаблон с параметрами N и Dims.... Вы можете создать экземпляр T, но не можете вывести из T значения N и Dims..., поскольку они являются параметрами.

То, что вы спрашиваете, похоже на: «Для функции f, которая принимает int x в качестве параметра, могу ли я узнать, каково значение x?». Конечно, нет. f — это функция, которой можно передать любой x.

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

 template <typename T>
 require std::is_derived_from<NDimContainer<T>,T>
 auto operator+(const T &lhs, const T& rhs) { 
     return T { lhs } += rhs;
 }

Где T — это экземпляр некоторого шаблона, который имел параметры N и Dims... Если это так, то из этого экземпляра T (типа) можно вывести параметры N и Dim..., такие, что T имеет тот же тип, что и некоторые U<N,Dims...>. Это возможно, но другой вопрос.

Извините за неясный вопрос, но вы выбрали правильный вариант, и просмотр параметров шаблона, как будто они являются параметрами функции, помог мне понять, почему это не работает. Я думаю, что это позор, потому что мне это показалось хорошо, поэтому мне было интересно, почему это не работает. Спасибо за ваш ответ.

Daniel Kříž 07.08.2024 13:19

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

Похожие вопросы