c++ - Что означает пустота, или как она влияет на Т в этом случае?




c++11 templates (2)

В общем, это просто означает, что вы собираетесь специализировать класс для типа void для обработки особого случая.

Вот демонстрационная программа.

#include <iostream>

template <class T = void>
struct A
{
    void operator ()( const T & t ) const 
    { 
        std::cout << "primary template\n"; 
        std::cout << 2 * t << '\n';
    }
};

template <>
struct A<>
{
    template <typename U>
    void operator ()( const U &u ) const 
    { 
        std::cout << "specialization for void\n";
        std::cout << 10 * u << '\n';
    }
};

int main()
{
    A<int>()( 1 );
    A<>()( 1 );
}

Его вывод

primary template
2
specialization for void
10

Поэтому я работал с моим другом на C ++, и мы столкнулись с этим в документации.

//(until C++14)
template<class T>
struct less;
//(since C++14)
template<class T = void>
struct less;

Теперь я знаю, как это работает с class T = int и то же самое для классов double и float и других типов. Но часть, которая меня очень смущает, - как действует пустота в этом случае? И каковы ограничения использования void?

Я спрашиваю об этом, потому что документация C ++ очень полезна, и я не могу найти где-либо еще, что объясняет это.


Учитывая ваш фрагмент кода, я собираюсь предположить, что вы ссылаетесь на объект функции из стандартной библиотеки, то есть en.cppreference.com/w/cpp/utility/functional/less .

В общем, template<class T = void> объявления template<class T = void> работает точно так же, как и для других типов (таких как, например, int ). Вкратце, когда объект этого класса создается без указания аргумента шаблона типа, тогда void будет вычитаться.

std::less<int> li;   // std::less<T = int>;
std::less<void> lv;  // std::less<T = void>;
std::less<> lv2;     // std::less<T = void>; exactly as one row above.

В этом конкретном случае std::less обеспечивает специализацию шаблона, когда T = void .

Объект std::less<void> является удобной специализацией, которая позволяет определять типы для «автоматического» сравнения с operator() . Более того, это нужно, когда вы хотите сравнить два разных типа, которые не являются неявно конвертируемыми.

Практический пример:

Предположим, у вас есть два объекта, которые вы можете сравнить.

/*Let us assume you have two objects you can compare*/
struct Foo;
struct Bar;

struct Foo {
  bool operator<(const Bar&) const;  
};

struct Bar {
  bool operator<(const Foo&) const;
};

Foo и Bar можно сравнить друг с другом, но они бывают разных типов.

Какой тип шаблона вы укажете для функтора std::less в этом случае?

void WrongCode() {
  std::less<Foo> l;
  l(Foo{}, Bar{});  // error
}

Если мы используем std::less<Foo> тогда функтор будет принимать только объекты типа Foo . (Конечно, то же самое для std::less<Bar> ).

Таким образом, стандарт предоставляет эту удобную специализацию, чтобы охватить этот случай.

void GoodCode() {
  std::less<> l;
  l(Foo{}, Bar{});  // this compile
}

GoodCode будет компилироваться, потому что типы operator() в std::less<void> автоматически вычитаются (и они могут даже отличаться).







templates