Как я могу использовать SFINAE, чтобы создать шаблонную функцию для контейнеров и определить тип возвращаемого значения на основе оператора? - PullRequest
0 голосов
/ 29 июня 2019

Я попытался создать функцию 'generateCombination', которая бы принимала два контейнера элементов и генерировала контейнер их комбинаций (например, {"hello"}, {"world", "friend"} производили {"hello world "," hello friend "}. Я пытался использовать SFINAE и decltype для оператора + (), чтобы определить тип возвращаемого значения, но я получил много ошибок с множеством разных попыток. Вот текущая версия:

#include <vector>

template<typename T, typename S>
using CombinationResult = decltype(operator+(T(),S()));

template<typename T, typename S>
using CombinationResultContainer = std::vector< CombinationResult<T, S>>;


template<typename T, typename S>
CombinationResultContainer<typename T::value_type,typename S::value_type> generateCombinations(T&& first, S&& second)
{
    CombinationResultContainer<typename T::value_type, typename S::value_type> result;
    result.reserve(first.size() * second.size());
    for (auto& t : first)
        for (auto& s : second)
            result.push_back(t + s);
    return result;
}



 void main()
{
    std::vector<std::string>v1;
    std::vector<std::string>v2;

    generateCombinations(v1,v2);
}

На данный момент я получаю ошибки: C2672 «generateCombination»: не найдена соответствующая перегруженная функция

C2893 Не удалось специализировать шаблон функции 'std :: vector> generateCombitions (T &&, S &&)'

Ответы [ 2 ]

0 голосов
/ 29 июня 2019

Вы ищете декартово произведение? Попробуйте диапазон V3

view::cartesian_product

Проблема вашего кода в том, что вам нужно удалить ссылку T и S Попробуйте

typename std::decay_t<T>::value_type

То же самое для S

или

typename boost::range_value<T>::type
0 голосов
/ 29 июня 2019

T и U не то, что вы думаете. Можно ожидать, что они оба будут std::vector<std::string>, но из-за того, что v1 и v2 являются lvalues, это означает, что T и U оба равны std::vector<std::string>& из-за свертывания ссылок . При попытке сделать:

CombinationResultContainer<typename T::value_type, typename S::value_type>

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

Поскольку в вашей функции ничто не зависит от того, что T или U являются ссылками lvalue или нет, я бы посоветовал вам использовать ссылки lvalue для const (T const& и U const&). Это выведет T и U как ожидаемые типы.

...