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

Рассмотрим следующее объявление:

template <class T>
bool DoSomething(const T& value);

template <class D>
bool DoSomething(const std::vector<D>& value);

Возможно ли как-то объединить это в одно объявление функции? Например, что-то вроде этого:

template <class T, class D> bool DoSomething(...);

Ответы [ 4 ]

1 голос
/ 07 ноября 2019

Короткий ответ : Обычно вы не можете.

Честный ответ : Да, это можно сделать, зависит от того, что вы планируете делать с аргументом. В абстрактном случае вам нужно будет обобщить прототип функции, но все еще иметь две специализации шаблона, использующие SFINAE, что делает три объявления вместо двух.

Длинный ответ : В некоторых случаях вы можетевоспользоваться if constexpr

#include <iostream>
#include <type_traits>
#include <vector>

template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};

template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};

template <class T> bool DoSomething(const T& arg) 
{ 
    if constexpr(is_specialization<T, std::vector>::value) 
    {
        return !arg.empty();    
    } else
    {
        return bool(arg);
    }
}

int main()
{
    std::vector<int> s;
    std::cout << DoSomething(s) << std::endl;
    std::cout << DoSomething(1) << std::endl;
}
1 голос
/ 07 ноября 2019

Ваш код

template <class T>
bool DoSomething(const T& value);

уже принимает std::vector. Если вы хотите сделать что-то в вашем методе DoSomething, которое отличается, если T является вектором, тогда вы можете использовать этот подход , чтобы проверить, является ли T определенным типом. Не забывайте, что шаблоны являются генераторами кода.

1 голос
/ 07 ноября 2019

Ну, template <class T> bool DoSomething(const T& value); также может быть calles с любым вектором. Если это работает, зависит от того, что вы пытаетесь сделать. Шаблоны - это просто генераторы кода. Таким образом, независимо от того, какой класс T, он может использоваться в качестве параметра шаблона, если он имеет все необходимые члены.

Например, будет работать следующее:

#include <iostream>
#include <vector>
#include <string>

class MyContainer {
public:
    size_t size() const
    {
        return 2;
    }

    int front() const
    {
        return 0;
    }

    int back() const
    {
        return 1;
    }
};

template<class T>
void foo(const T& t)
{
    if (t.size() >= 2)
    {
        std::cout << "(" << t.front() << ", " << t.back() << ")" << std::endl;
    }
}

int main()
{
    std::vector<std::string> stringVec{ "abc", "def" };

    MyContainer cont;

    foo(stringVec); // prints "(abc, def)"
    foo(cont); // prints "(0, 1)"
}

Это потому, что оба MyContainer и std::vector<std::string> имеют все методы, которые используются в шаблоне. На самом деле этот код должен работать практически со всеми STL-контейнерами.

1 голос
/ 07 ноября 2019

Параметры шаблона могут быть типами, не типами и шаблонами.

И я полагаю, вы смотрите на что-то вроде этого

#include <iostream>
#include <list>
#include <vector>
#include <string>

template <typename T, template <typename, typename> class Cont > 
class Matrix{
public:
  explicit Matrix(std::initializer_list<T> inList): data(inList){
for (auto d: data) std::cout << d << " ";
  }
  int getSize() const{
    return data.size();
  }

private:
  Cont<T, std::allocator<T>> data;  
};

int main(){

  std::cout << std::endl;
  Matrix<int, std::vector> myIntVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
  std::cout << std::endl;
  std::cout << "myIntVec.getSize(): " << myIntVec.getSize() << std::endl;
  Matrix<std::string, std::list> myStringList{"one", "two", "three", "four"};  
  std::cout << std::endl;
  std::cout << "myStringList.getSize(): " << myStringList.getSize() << std::endl;

  std::cout << std::endl;

}

Матрица - это простой шаблон класса, который можетбыть инициализирован std::initializer_list. Матрица может использоваться с std::vector или std::list для хранения ее значений.

live Demo

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