透明操作员函数

Gra*_*ell 26 c++ c++11 visual-studio-2013 c++14

Visual Studio 2013 Preview支持名为(根据页面)"透明运算符函数" 的C++ 14功能.我不清楚这意味着什么.我找到的最接近的C++ 14提案就是这个,但我不确定它是否是同一个东西:http: //www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421

我正在寻找一个更明确的解释,它是什么,为什么它是一个改进,也许是一个证明其使用的片段.

Rap*_*ptz 23

透明的运算符仿函数提议是一种使用广义仿函数的方法<functional>.我个人认为该提案本身有一个非常好的例子,可以帮助说明它的必要性.但是我会继续尝试解释它.

假设你有一个功能,一个非常基本的功能提醒你:

template<typename T, typename U>
auto less_than(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)) {
    return std::forward<T>(t) < std::forward<U>(u);
}
Run Code Online (Sandbox Code Playgroud)

但是,您希望在标题中使用此通用函数<algorithm>.你有两个选择,使它成为一个struct functor:

struct MyLessThanFunctor {
    template<typename T, typename U>
    auto operator()(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)){
        return std::forward<T>(t) < std::forward<U>(u);
    }
};
Run Code Online (Sandbox Code Playgroud)

或者在C++ 14中,制作一个多态lambda:

[](auto&& t, auto&& u) -> decltype(auto) { 
    return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u); 
}
Run Code Online (Sandbox Code Playgroud)

当在如下算法中使用时,两者都非常冗长:

int main() {
    std::vector<int> v = {112,12,1281271,1919101,29181,412,1 };
    std::sort(std::begin(v), std::end(v), MyLessThanFunctor()); // one
    std::sort(std::begin(v), std::end(v), [](auto&& t, auto&& u) -> decltype(auto) { 
        return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u); 
    });
}
Run Code Online (Sandbox Code Playgroud)

该提案旨在通过这样做来使其更紧凑和更广泛:

std::sort(std::begin(v), std::end(v), std::less<>());
Run Code Online (Sandbox Code Playgroud)

这为您提供了完美的转发,并解决了因更换容器而导致的截断或问题,而不是文件中提到的容器指定的基础类型.

假设您有一个非广义仿函数:

struct Functor {
    bool operator()(uint32_t a, uint32_t b) {
        return a < b;
    }
};
Run Code Online (Sandbox Code Playgroud)

并且你std::vector<uint32_t>和它一起使用它并且它可以很好地工作,但是你忘记了你的仿函数没有被推广并且与你一起使用它std::vector<uint64_t>.你能看到出现的问题吗?在比较之前,元素将被截断,这可能不是用户想要的.广义仿函数会在出现之前为您解决此问题.

  • Praetorian,考虑C++ 11的异构lower_bound(),其中范围和期望值可以有不同的类型.C++ 98较少<T>需要(const T&,const T&),因此无论您选择什么T,都无法执行异构比较.即使对于像std :: string和const char*这样的简单情况,这也很重要. (10认同)
  • 你可以使用`std :: less`等.即使没有实施这些透明的算符,但它还是非常不合适.`std :: sort(std :: begin(v),std :: end(v),std :: less <std :: remove_reference <decltype(v [0])> :: type>());` (3认同)