Нормализовать построение объектов, которые содержат значения времени компиляции * или * времени выполнения - PullRequest
0 голосов
/ 04 января 2019

Допустим, у меня есть два класса

template <int A_, int B_>
class One {
    public:
        static constexpr auto A = A_;
        static constexpr auto B = B_;
        const int C;
        One(int C) : C(C) {}
};

class Two {
    public:
        const int A;
        const int B;
        const int C;
        Two(int A, int B, int C) : A(A), B(B), C(C) {}
};

Единственное отличие состоит в том, что класс One принимает параметры A и B во время компиляции, тогда как Two принимает параметры во время выполнения. Существует несколько операций над этими по существу эквивалентными типами, поэтому их можно записать в общем виде:

template <typename T>
auto min(const T& a, const T& b) {
    if (a.C < b.C) {
        return T(a.A+b.A, a.B+b.B, a.C);
    } else {
        return T(a.A+b.A, a.B+b.B, b.C);
    }
}

Проблема с вышесказанным - конструкция выходного объекта. Два типа One и Two могут использоваться одинаково для доступа к элементам A, B и C, получения их типов и т. Д. Однако из-за несоответствия в конструкция объектов (аргументы функции подачи или аргументы шаблона подачи), если для операции требуется создание нового объекта, не может быть записано в общем виде.

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

1 Ответ

0 голосов
/ 04 января 2019

Вы можете создать свой постоянный класс int, похожий на std::integral_constant, но дополненный необходимой функцией, например:

template <int N> struct int_c
{
    static constexpr int value = N;
};

template <int N1, int N2>
constexpr int_c<N1 + N2> operator + (int_c<N1>, int_c<N2>) { return {}; }

template <int N>
std::ostream& operator << (std::ostream& os, int_c<N>) { return os << N; }

Затем измените свой класс, чтобы иметь близкий интерфейс, особенно для конструктора, добавьте метод фабрики:

template <int A_, int B_>
class One {
public:
    static constexpr int_c<A_> A{};
    static constexpr int_c<B_> B{};
    const int C;
    One(int C) : C(C) {}

    template <typename IA, typename IB>
    static One<IA::value, IB::value> Create(IA, IB, int C) { return {C}; } 
};

class Two {
public:
    const int A;
    const int B;
    const int C;
    Two(int A, int B, int C) : A(A), B(B), C(C) {}

    static Two Create(int A, int B, int C) { return {A, B, C}; } 
};

Тогда ваш общий код может выглядеть так:

template <typename T1, typename T2>
auto min(const T1& a, const T2& b) {
    if (a.C < b.C) {
        return T1::Create(a.A + b.A, a.B + b.B, a.C);
    } else {
        return T1::Create(a.A + b.A, a.B + b.B, b.C);
    }
}

Демо

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