11

我正在玩新explicit的演员操作员。如果你写类似

struct Data {
    explicit operator string(); 
};

不可能意外转换Datastring. darget 数据类型bool是一个例外:在某些情况下,即使标记为explicit- contextual conversion ,也允许隐式转换。因此,您可以在示例中使用此数据类型if(...)

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

段落“25.4.(2) 排序和相关操作”似乎也允许标准容器Compare的函子这样做。但是我对 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之前没有。operator bool()而我对“25.4.(2)”的理解是,这也应该使用`explicit.

我是否正确理解了转换setexplicit bool应该起作用的标准?那么这可能是gcc中的一个错误,还是我理解错误?

4

2 回答 2

3

我对标准的解读略有不同——第 25.4 节处理排序算法而不是排序容器;25.4.(1) 中建立的上下文意味着 25.4.(2) 中指定的比较对象的属性适用于 25.4 中的算法,而不适用于已排序的容器

1 25.4 中的所有操作都有两种版本:一种采用比较类型的函数对象,另一种采用运算符。

2 比较是一个函数对象类型 (20.8)。应用于比较类型对象的函数调用操作的返回值,当上下文转换为 bool (4) 时,如果调用的第一个参数小于第二个参数,则返回 true,否则返回 false。比较 comp 始终用于假设排序关系的算法。假定 comp 不会通过取消引用的迭代器应用任何非常量函数。

我不知道您的示例是否应该有效,但我认为第 25.4 节不适用于此处。

使用向量和 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());
}

编辑:

关联容器的比较参数根据第 25.4 节定义:

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

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

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

于 2011-11-04T19:22:10.090 回答
2

我是否正确理解了对于 set 显式 bool 转换也应该有效的标准?

这是规范的灰色地带。比较函数的返回值需要“可转换为布尔值”。但这意味着什么explicit operator bool()尚不清楚。

例如,可以这样写std::set比较用法:

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

或者,可以这样做:

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

在 C++11 下,这两种技术在技术上都是合法的吗?不知道。显然,第二个失败 if operator bool()is 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++ 错误提交。

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


关于上下文转换

第 4 节第 3 款规定:

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

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

不过,当您可以提供帮助时,我仍然会避免这样做。

于 2011-11-04T19:11:25.613 回答