我试图了解std :: less是如何实现的,所以我可以说
template <typename T>
struct myless
{
constexpr bool operator()(const T &lhs, const T &rhs) const
{
return lhs < rhs;
}
};
template <typename A, typename B, typename U = myless> // std::less works
bool f(A a, B b, U u = U())
{
return u(a, b);
}
int main()
{
std::cout << std::boolalpha;
std::cout << f("AB/CD", "CD/AB") << '\n';
std::cout << f(100, 10) << '\n';
}
这不起作用。有什么建议吗?
答案 0 :(得分:3)
f("AB/CD", "CD/AB",)
(逗号)中有拼写错误。
它应该是typename U = myless<A>
,因为myless
不在std
命名空间中。
参数也应该通过引用传递:bool f(const A& a, const B& b, const U& u = U())
。
std::less
需要两个操作数具有相同的类型(逻辑上),并且myless
也是这样定义的。因此,对myless<A>
使用U
会使B
对象转换为A
进行比较(通过使用其复制构造函数创建临时对象)。
从C ++ 14开始,还有专门化std::less<void>
,其中操作数可以有不同的类型,而返回类型不是bool。它将一对一映射到operator<
所做的事情。请参阅http://en.cppreference.com/w/cpp/utility/functional/less_void。
修正后的代码版本:
#include <iostream>
template <typename T>
struct myless
{
constexpr bool operator()(const T &lhs, const T &rhs) const
{
return lhs < rhs;
}
};
template <typename A, typename B, typename U = myless<A>>
bool f(const A& a, const B& b, const U& u = U())
{
return u(a, b);
}
int main()
{
std::cout << std::boolalpha;
std::cout << f("AB/CD", "CD/AB") << '\n';
std::cout << f(100, 10) << '\n';
}
对于可以具有不同类型的版本,以及非bool返回类型:
struct myless2 {
template<class T, class U>
constexpr auto operator()(const T& t, const U& u) const -> decltype(t < u) {
return t < u;
}
};
std::less<void>
似乎也支持r值引用,因为operator<
的定义是这样的(当时可能做比其他事情更多的事情。)
答案 1 :(得分:2)
您的myless
模板只采用一种类型,但您的f
函数有两种类型(即它们可能是不同的类型)。它可以支持这一点,但它涉及更多。你有意打算做以下事吗?
template<typename T, typename U = myless<T>>
bool f(T a, T b, U u = U())
{
return u(a, b);
}
正如@vscoftco所指出的,支持不同类型可能是一个预期的用例。如果要明确支持不同的类型,那么我会像这样实现它。
template<typename A, typename B, typename U = myless<typename std::common_type<A, B>::type>>
bool f(A a, B b, U u = U())
{
return u(a, b);
}
此解决方案似乎也与SFINAE兼容(C ++ 17),http://en.cppreference.com/w/cpp/types/common_type。
如果sizeof ...(T)为零或者没有常见类型,则不定义成员类型(std :: common_type对SFINAE友好)