Как дешифровать шаблонный метод C ++? - PullRequest
2 голосов
/ 07 февраля 2020

Я пишу интерфейсы через концепции для проверки реализации.

Нет проблем с обычными методами:

// Interface realization
struct Realization
{
    int* TestMethod(const std::string& aStr)
    {
        return (int *) aStr.c_str();
    }
};

// Concept
template <typename T>
concept IRealization = std::is_same_v<decltype(&T::TestMethod), int* (T::*)(const std::string&)>;

// and then, for example
void Check()
{
    static_assert(IRealization<Realization>)
}

, но когда я пытаюсь написать аналогичную проверку для метода шаблона:

// Interface realization
struct Realization
{
    template <typename T>
    int* TemplateMethod(const T& aStr)
    {
        return (int *) aStr.c_str();
    }
};

, я столкнулся с проблемой dectype шаблонного метода, потому что я не могу написать

decltype(&RealizationImpl::TemplateMethod)

(во время проверки интерфейса я не знаю тип, который будет быть замененным)

Скажите, пожалуйста, можно ли каким-то образом получить сигнатуру функции шаблона без типа или иным образом решить мою проблему? Спасибо!

Ответы [ 2 ]

4 голосов
/ 07 февраля 2020

Вы не должны писать такие концепции. Концепция никогда не должна проверять что-либо, как указано c как функцию-член с точной подписью. Вместо этого концепция должна сказать, что, учитывая экземпляр рассматриваемого типа, я должен быть в состоянии сделать i.memberFunc(...), где ... - список параметров.

Например, ваша концепция "IRealization" (пожалуйста, не используйте префиксы для I. Понятия - это , а не интерфейсы). Следует сказать, что "T должен иметь функцию-член, которая может быть вызвана с помощью аргумента std::string и приводит к чему-то, что конвертируется в int. " Это будет выглядеть так:

template <typename T>
concept IRealization = requires(T t, std::string str)
{
  { t.TestMethod(str) } -> convertible_to<int>;
};

Это позволяет пользователю предоставить TestMethod, который принимает, например, std::string_view вместо std::string. Нет смысла быть таким невероятно ограничительным для типа.

Концепция, проверяющая наличие в 1011 * функции-члена, которая может вызываться с каким-либо типом U, должна была бы быть шаблонной как для T, так и для U:

template <typename T, typename U>
concept IRealization = requires(T t, U u)
{
  { t.TestMethod(u) } -> convertible_to<int>;
};
1 голос
/ 07 февраля 2020

В чем проблема с добавлением другого типа в концепт?

// Concept
template <typename T, typename U>
concept IRealization = std::is_same_v<decltype(&T::template TestMethod<U>), int* (T::*)(const U&)>;

Например.

Вы даже можете сделать его красивее, создав typedef -

template<typename T, typename U>
using FuncT = decltype(&T::template TestMethod<U>);
...