c++ 为什么这个模板类可以工作,尽管使用std::不那么奇怪

lyfkaqu1  于 2022-12-05  发布在  其他
关注(0)|答案(1)|浏览(138)

以下代码有效:

#include <iostream>

constexpr static auto less = std::less{};

#include <string>

std::string a = "1";
std::string b = "1";

int main(){
    std::cout << ( less( 6, 3 ) ? "Y" : "N" ) << '\n';
    std::cout << ( less( a, b ) ? "Y" : "N" ) << '\n';
}

根据en.cppreference.com,std::less的实现方式如下:

template<class T>
struct Less{
    constexpr bool operator()(const T &lhs, const T &rhs) const{
        return lhs < rhs;
    }   
};

但如果这是真的,std::less{};是如何工作的呢?它需要传递类型-std::less<int>{};
或者,如果实现是这样的:

struct Less{
    template<class T>
    constexpr bool operator()(const T &lhs, const T &rhs) const{
        return lhs < rhs;
    }   
};

一切都会好的。
但是如果这是事实,为什么要使用class而不是lambda呢?
奇怪的是,这段代码也能正常工作:

#include <iostream>

constexpr static auto less = std::less<int>{};

#include <string>

std::string a = "1";
std::string b = "1";

int main(){
//  obviously for strings it no longer works.
//  std::cout << ( less( 6, 3 ) ? "Y" : "N" ) << '\n';
    std::cout << ( less( a, b ) ? "Y" : "N" ) << '\n';
}

那么到底是怎么回事呢?

dxxyhpgq

dxxyhpgq1#

由于C++14 std::less声明为

template< class T = void >
struct less;

它有一个specialization for void,它有一个operator(),其形式为

template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
  -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs));

这个operator()为您推导出参数的类型并返回lhs < rhs。这就是允许您编译第一个代码块的原因。
在第二个示例中,将less切换为

constexpr static auto less = std::less<int>{};

这就迫使您使用只适用于int的比较器。

相关问题