在std :: greater和std :: less上的C++ 11条件表达式得到了不同类型的错误

Rob*_*Hsu 8 c++ c++11

以下与条件表达式相关的代码:

typedef unsigned char uchar;
uchar data[100];
// assign something to array[] here
uchar *start = data;
uchar *end = data+100;
bool cond = f();  // f() could return true or false
uchar *itr = std::upper_bound(start, end, uchar(20), 
                cond? std::greater<uchar>() : std::less<uchar>());
Run Code Online (Sandbox Code Playgroud)

得到这样的错误:

error: operands to ?: have different types 
‘std::greater<unsigned char>’ and ‘std::less<unsigned char>’
Run Code Online (Sandbox Code Playgroud)

这是编译器错误吗?根据我的直觉,这两个仿函数应该具有相同的类型.

Zer*_*ges 5

std::greater并且std::less是不同的类型(std::string和和不同std::unordered_map).它们只提供相同的接口(operator()).

有条件的经营者cond ? expr1 : expr2要求,这expr1expr2是同一类型的(或一个隐式转换为另一种),这是不是你的情况.

您可以使用

char *itr;
if (cond)
    itr = std::upper_bound(start, end, uchar(20), std::greater<uchar>{});
else
    itr = std::upper_bound(start, end, uchar(20), std::less<uchar>{});
Run Code Online (Sandbox Code Playgroud)

或者如果你不想拥有两条几乎相同的线条,你可以用普通的lambda来帮助自己

auto upper_bound = [&](const auto& cmp){
    return std::upper_bound(start, end, uchar(20), cmp);
};
if (cond)
    itr = upper_bound(std::greater<uchar>{});
else
    itr = upper_bound(std::less<uchar>{});
Run Code Online (Sandbox Code Playgroud)


Yak*_*ont 3

C++ 中的函子传统上不共享类型。这使得编译器可以轻松准确地理解正在调用哪个函子,并导致性能提升。

C++中有一种称为类型擦除的机制。在这里,您会忘记是什么使两种类型不同,而只记得是什么使它们相同。

C++ 中最常见的类型擦除是std::function. 此函数此处类型删除一个无状态模板,该模板接受两个T const&并返回一个bool

template<class T, template<class...>class Z>
std::function< bool(T const&, T const&) >
comp() { return Z<T>{}; }
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用您的代码并执行以下操作:

uchar *itr = std::upper_bound(start, end, uchar(20), 
            cond? comp<uchar, std::greater>() : comp<uchar, std::less>());
Run Code Online (Sandbox Code Playgroud)

或者:

template<class T>
using comp_sig = bool(T const&, T const&);

template<class T, template<class...>class Z>
comp_sig<T>* comp() {
  return [](T const& lhs, T const& rhs)->bool{
    return Z<T>{}(lhs, rhs);
  };
}
Run Code Online (Sandbox Code Playgroud)

它为您提供根据需要调用less或的函数指针。greater对于编译器来说,这个版本可能比第一个版本更容易优化std::function,因为编译器非常擅长优化常量函数指针。