1

这段代码怎么编译不出来?为什么bs[1]不能推断bool

有没有解决这个问题的通用方法?

#include <iostream>
#include <string>
#include <bitset>
using namespace std;

template<typename T> struct StringConverter{};
template<> struct StringConverter<bool>{
    std::string operator()(const bool &i){ return i?"true":"false"; }   
};

template<typename T> std::string to_string(const T &val){
    return StringConverter<T>()(val);
}

int main(){
    // this does not compile
    std::bitset<10> bs;
    std::cout << to_string(bs[0]) << std::endl;

    // this does
    const std::bitset<10> bs_const;
    std::cout << to_string(bs_const[0]) << std::endl;
}

编译器错误:

main.cpp:12:12: error: type 'StringConverter<std::bitset<10>::reference>' does not provide a call operator
    return StringConverter<T>()(val);
           ^~~~~~~~~~~~~~~~~~~~
main.cpp:18:18: note: in instantiation of function template specialization 'to_string<std::bitset<10>::reference>' requested here
    std::cout << to_string(bs[0]) << std::endl;
                 ^
1 error generated.
4

2 回答 2

3

非常量 bitset::operator[] 返回一个代理对象而不是布尔值(必须这样做,因为该代理可用于更改位值)。const bitset::operator[] 但是只返回一个布尔值(不是引用,只是一个普通布尔值),因此它与 StringConverter[

于 2017-12-09T22:30:17.990 回答
1

如果您检查 的声明operator[],您会注意到它有两个重载 -const一个返回bool并在您的第二个示例中使用const,另一个返回类型为 的对象std::bitset::reference

后者用于位字段修改,它绝对不能是 a bool&,因为它必须寻址特定位。对于这些代理返回类型,您遇到的问题很常见(这是我应该提到的地方vector<bool>)。

作为一种可能的解决方案,您可以使用std::bitset::reference可转换为bool(并且不可转换为您可能用于您的StringConverter专业化的任何其他可能的类型)的事实。

于 2017-12-09T22:44:38.867 回答