隐式转换为显式bool类型以分类容器?

时间:2011-11-04 17:44:00

标签: c++ c++11 boolean explicit

我正在使用新的explicit来进行强制转换操作。如果你写了像

这样的东西
struct Data {
    explicit operator string(); 
};

无法将Data意外转换为string。目标数据类型bool是一个例外:在某些情况下,即使标记为explicit - 上下文转换,也允许隐式转换。因此,您可以在if(...)中使用此数据类型,例如:

struct Ok {
    explicit operator bool(); // allowed in if(...) anyway
};

段落“25.4。(2)排序和相关操作”似乎允许<{>>标准容器的Compare仿函数,如{{1}也是。但是我对gcc-4.7.0的尝试失败了,我注意到这是我的错误理解还是gcc中的错误?

set

#include <set> struct YesNo { // Return value type of Comperator int val_; explicit YesNo(int y) : val_{y} {} /* explicit */ operator bool() { return val_!=0; } }; static const YesNo yes{1}; static const YesNo no{0}; struct LessYesNo { // Comperator with special return values YesNo operator()(int a, int b) const { return a<b ? yes : no; } }; int main() { std::set<int,LessYesNo> data {2,3,4,1,2}; } 之前没有explicit示例编译。而我对“25.4。(2)”的理解是,这也应该用 编译`。

我是否正确理解了Std,operator bool() set explicit转换应该有效?这可能是gcc中的错误,或者是我明白了什么问题?

2 个答案:

答案 0 :(得分:3)

我对标准的阅读有点不同 - 第25.4节涉及排序算法而不是排序容器;在25.4。(1)中建立的上下文意味着25.4。(2)中规定的比较对象的属性适用于25.4中的算法,而不是分类容器

  

1   25.4中的所有操作都有两个版本:一个需要a   比较类型的函数对象和使用运算符的函数对象。

     

2   Compare是一个函数对象类型(20.8)。的返回值   函数调用操作应用于Compare类型的对象,何时   上下文转换为bool(4),如果是第一个参数,则返回true   呼叫小于第二个,否则为假。比较comp   在整个过程中用于假设有序关系的算法。它是   假设comp不会通过的应用任何非常数函数   解除引用的迭代器。

我不知道你的例子是否有效,但我不认为第25.4节适用于此。

使用vector和std :: sort进行快速测试:

#include <list>
#include <algorithm>

struct YesNo { // Return value type of Comperator
    int val_;
    explicit YesNo(int y) : val_{y} {}
    explicit operator bool() { return val_!=0; }
};

static const YesNo yes{1};
static const YesNo no{0};

struct LessYesNo {  // Comperator with special return values
    YesNo operator()(int a, int b) const {
        return a<b ? yes : no;
    }
};

int main() {
    std::vector<int> data {2,3,4,1,2};
    std::sort(std::begin(data), std::end(data), LessYesNo());
}

编辑:

关联容器的Compare参数是根据secion 25.4:

定义的
  

1关联容器提供基于密钥的快速数据检索。该库提供了四种基本类型的关联容器:set,multiset,map和multimap。

     

2每个关联容器都在Key上进行参数化和排序关系比较   在Key的元素上引入严格的弱排序(25.4)。此外,map和multimap将任意类型T与Key相关联。 Compare类型的对象称为容器的比较对象。

和23.就我所看到的那样,在Compare的类型上没有其他条件,因此假设满足25.4约束的类型同样适用似乎是合理的。

答案 1 :(得分:2)

  

我是否正确理解了Std,对于set来说,明确的bool转换应该有效吗?

这是规范的灰色区域。比较函数的返回值必须是“可转换为bool”。但是根据explicit operator bool()的含义还不清楚。

例如,可以将std::set的比较用法写成:

CompFunc functor;
if(functor(input, currVal))
  ...

或者,可以这样做:

CompFunc functor;
bool test = functor(input, currVal);
if(test)
  ...

这两个技术在C ++ 11下都是合法的吗?不知道。显然,如果operator bool()explicit,则第二个失败。

我查看了std::shared_ptr的定义,它也有explicit operator bool()。它还说std::shared_ptr在第20.7.2.2节第2段中“可转换为布尔”。

所以我猜第二个版本实现如下:

CompFunc functor;
bool test = static_cast<bool>(functor(input, currVal));
if(test)
  ...

事实上,规范中没有明确说明它意味着它应该作为缺陷报告提交。但它应该也可以作为GCC / libstdc ++ bug提交。

就个人而言,为了安全起见,我不会依赖它。


关于上下文转换

第4节第3段指出:

  

在这样的上下文中出现的表达式e被称为在上下文中被转换为bool并且当且仅当声明bool t(e)时才是格式良好的;对于一些发明的临时变量来说,这是一个良好的形式

因此“上下文可转换为bool”的操作意味着explicit operator bool()将起作用。由于std::set的“比较”函子必须符合25.4的要求,并且这些要求包括“上下文转换为bool”,它看起来像是GCC / libstdc ++错误。

但是,当你能提供帮助时,我仍然会避免这样做。