2013-07-19 52 views
23

Visual Studio 2013预览支持称为“透明运算符函子”的C++ 14功能(根据this页面)。我不清楚这意味着什么。我找到的最近的C++ 14建议是这样的,但我不确定它是否是相同的东西: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421透明运算符函数器

我正在寻找更清楚的解释它是什么,为什么它是一种改进,以及也许是一个展示其用途的片段。

+0

如果相同,它可以让你替换'bool less :: operator()(int const&lhs,int const&rhs)const {return lhs (sth :: forward (lhs)(rhs)){return std :: forward (lhs)(rhs); },这是一个完美的转发“透明”的调用。 – Yakk

+4

N3421是同样的东西 - 它在那次会议上被投票到C++ 14而没有修改,这就是我在2013 Preview中实现的。我认为第二节“动机和范围”清楚地解释了问题和解决方案,我认为第八节“实施”中的例子证明了它的用处。你困惑什么? –

+0

“Visual C++新增功能”页面没有提到N3421提案,所以我想我会问这里。我现在清楚了。感谢您添加它。 – GravityWell

回答

22

透明运算符函子提议是作为一种方法来使位于<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); 
} 

但是要在<algorithm>头使用此广义功能。你有两个选择,使之成为结构函子:

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); 
    } 
}; 

还是在C++ 14,做一个多态的λ:

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

在算法中使用像这样的时候两者都非常详细:

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); 
    }); 
} 

这项提案的目的是使其更紧凑,并通过这样做,而不是一概而论:

std::sort(std::begin(v), std::end(v), std::less<>()); 

这为您提供了完美的转发,并解决了由于更改容器而导致截断或问题的问题,但解决了由论文提到的容器指定的基础类型所带来的问题。

假设你有一个非广义函子:

struct Functor { 
    bool operator()(uint32_t a, uint32_t b) { 
     return a < b; 
    } 
}; 

你用你的std::vector<uint32_t>使用它,它工作一切正常,但你忘记你的仿函数没有被推广,并与您的std::vector<uint64_t>使用它。你能看到已经出现的问题吗?元素在被比较之前会被截断,这可能不是用户想要的。广义仿函数在出现之前就为你解决了这个问题。

+2

你可以使用'std :: less'等。即使没有实现这些透明仿函数,但它是一个更大的不稳定。'std :: sort(std :: begin(v),std :: end(v),std :: less :: type>());' – Praetorian

+9

Praetorian,考虑C++ 11的异构lower_bound(),其中范围和期望值可以有不同的类型。 C++ 98更少需要(const T&,const T&),所以不管你选择什么,你都不能执行异构比较。即使对于像std :: string和const char *这样的简单情况,这也很重要。 –

+0

等效lambda是'[](auto && t,auto && u) - > decltype(auto){return std :: forward (t)(u); '',可悲的是 –