шаблонная структура частичная специализация с enable_if или чем-то похожим - PullRequest
0 голосов
/ 18 февраля 2019

Я ищу способ использовать std :: enable_if или что-то похожее для расширения уже существующей точки настройки, которая будет работать как специализация A<T> ниже (просто фиктивный пример):

// customisation point structure in external lib
template<typename T>
struct A
{
    typedef T type;
};

//---------------------------------------------
#include <vector>

template <typename T>
concept bool Floating = std::is_floating_point<T>::value;

// specialisation with enable_if style that doesn't require change to external lib
template<Floating T>
struct A<T>
{
    typedef std::vector<T> type;
};

int main()
{
    static_assert(std::is_same<A<int>::type, int>::value, "");
    static_assert(std::is_same<A<float>::type, std::vector<float>>::value, "");

    return 0;
}

Проблема в том, что у меня есть следующие ограничения:

  • struct A не может быть изменена для принятия двух параметров шаблона template<typename T, typename = void>, так как эта структура определена во внешней библиотеке
  • can 'не используйте понятия lite (так как некоторые люди считают необходимым отложить их стандартизацию на несколько лет в будущем ...)
  • не хотят путать код на всех сайтах вызовов с чем-то вроде A<type_mod<float>> так как это было бы уродливо и подвержено ошибкам (то же самое относится и к использованию макросов)
  • не хочу писать внешний генератор кода

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

1 Ответ

0 голосов
/ 18 февраля 2019

Чтобы убедиться, что я правильно понимаю вопрос, вы ищете что-то эквивалентное коду, который вы разместили, но используете только C ++ 14 (без понятий)?

Я думаю, что первое ограничение выУпомянутое («структура A не может быть изменена для принятия двух параметров шаблона») является самой большой проблемой.Я не знаю ни одного способа специализировать существующий шаблон с одним аргументом сразу для целого «класса» типов (например, типов с плавающей запятой) без использования понятий.

Так что я думаюСтрогий ответ на ваш вопрос: «Нет, это невозможно».

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

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

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

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

// customisation point structure in external lib
template<typename T>
struct A
{
    typedef T type;
};

//---------------------------------------------
#include <vector>

template<typename T, bool is_float>
struct Av2impl
{
    typedef T type;
};

template<typename T>
struct Av2impl<T, true>
{
    typedef std::vector<T> type;
};

template<typename T>
struct Av2
{
    typedef typename Av2impl<T, std::is_floating_point<T>::value>::type type;
};

// force all code after this point to use Av2 instead of A
#define A Av2

int main()
{
    static_assert(std::is_same<A<int>::type, int>::value, "");
    static_assert(std::is_same<A<float>::type, std::vector<float>>::value, "");

    return 0;
}
...