如何使用is_transparent类型的比较器?

时间:2015-02-01 17:10:41

标签: c++ c++14 stdset

使用C ++ 14,我们可以将一些关联容器(如std :: set)的元素与存储在容器中的其他类型进行比较。当比较器is_transparent表示为一种类型时,它应该起作用(参见例如std::set::find)。

假设我有一个字符串包装器,它对字符串执行一些检查(如果它的格式是有效的格式等等 - 不是很重要,但是构造它很重,我想避免它+它可以抛出异常并且它存储在std :: set中以具有唯一值的容器。我该如何为它写一个比较器?它应该像下面那样吗?我可以重载并使用我的sw::operator<()来实现相同的目标吗?

class sw
{
public:
    explicit sw(const std::string& s) : s_(s) { /* dragons be here */ }
    const std::string& getString() const { return s_; }

    bool operator<(const sw& other) const { return s_ < other.s_; }

private:
    std::string s_;
};

struct Comparator
{
    using is_transparent = std::true_type;

    bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; }
    bool operator()(const std::string& lhs, const sw& rhs) const { return lhs < rhs.getString(); }
    bool operator()(const sw& lhs, const sw& rhs) const { return lhs < rhs; }
};

int main() 
{
    std::set<sw, Comparator> swSet{ sw{"A"}, sw{"B"}, sw{"C"} };
    std::cout << std::boolalpha << (swSet.find(std::string("A")) != swSet.end()) << std::endl;
}

我相信上面的代码应该按预期工作,但是当我使用g ++ 4.9和clang ++ 3.6进行测试时,两者都产生了关于从stringkey_type的转换丢失的错误,就像字符串一样Comparator::operator()的重载从未被考虑过。我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

是的,该代码是正确的,但重载operator<以允许将您的类型与std::string进行比较然后只使用std::less<>(即std::less<void>)会更简单这已经是“透明的”了。

inline bool operator<(const sw& lhs, const std::string& rhs) { return lhs.getString() < rhs; }
inline bool operator<(const std::string& lhs, const sw& rhs) { return lhs < rhs.getString(); }

std::set<sw, std::less<>> swSet{ sw{"A"}, sw{"B"}, sw{"C"} };

此外,值得注意的是,您定义is_transparent的内容并不重要,其中任何一个都与您对其的定义具有相同的效果:

using is_transparent = std::false_type;

using is_transparent = void;