以下与条件表达式相关的代码:
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)
这是编译器错误吗?根据我的直觉,这两个仿函数应该具有相同的类型.
std::greater
并且std::less
是不同的类型(std::string
和和不同std::unordered_map
).它们只提供相同的接口(operator()
).
有条件的经营者cond ? expr1 : expr2
要求,这expr1
和expr2
是同一类型的(或一个隐式转换为另一种),这是不是你的情况.
您可以使用
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)
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
,因为编译器非常擅长优化常量函数指针。
归档时间: |
|
查看次数: |
363 次 |
最近记录: |