THRIFT-922. cpp: Fix C++ compilation when using list<bool>
The STL specializes vector<bool> to store the values as individual bits, rather
than bools. Therefore, when using a Thrift list<bool>, readBool() gets invoked
not with a bool&, but with a std::vector<bool>::reference.
TProtocol does provide a readBool(std::vector<bool>::reference) implementation.
However, almost all TProtocol subclasses defined only readBool(bool&), which
hides the other overloaded versions of readBool(). As a result, the code
worked only when accessing TProtocol objects via a "TProtocol*", and not
directly via the subclass type. When using C++ templates, protocol objects do
get invoked via pointers to the subclass type, causing compile failures when
std::vector<bool> is used.
This change updates the various TProtocol implementations to also provide
readBool(std::vector<bool>::reference).
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@1005137 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/protocol/TBinaryProtocol.h b/lib/cpp/src/protocol/TBinaryProtocol.h
index ca45294..edb8834 100644
--- a/lib/cpp/src/protocol/TBinaryProtocol.h
+++ b/lib/cpp/src/protocol/TBinaryProtocol.h
@@ -174,6 +174,8 @@
inline uint32_t readSetEnd();
inline uint32_t readBool(bool& value);
+ // Provide the default readBool() implementation for std::vector<bool>
+ using TVirtualProtocol< TBinaryProtocolT<Transport_> >::readBool;
inline uint32_t readByte(int8_t& byte);
diff --git a/lib/cpp/src/protocol/TCompactProtocol.h b/lib/cpp/src/protocol/TCompactProtocol.h
index 2150cde..19a0160 100644
--- a/lib/cpp/src/protocol/TCompactProtocol.h
+++ b/lib/cpp/src/protocol/TCompactProtocol.h
@@ -192,6 +192,8 @@
uint32_t& size);
uint32_t readBool(bool& value);
+ // Provide the default readBool() implementation for std::vector<bool>
+ using TVirtualProtocol< TCompactProtocolT<Transport_> >::readBool;
uint32_t readByte(int8_t& byte);
diff --git a/lib/cpp/src/protocol/TDenseProtocol.h b/lib/cpp/src/protocol/TDenseProtocol.h
index ca2d427..438ed89 100644
--- a/lib/cpp/src/protocol/TDenseProtocol.h
+++ b/lib/cpp/src/protocol/TDenseProtocol.h
@@ -189,6 +189,8 @@
uint32_t readSetEnd();
uint32_t readBool(bool& value);
+ // Provide the default readBool() implementation for std::vector<bool>
+ using TVirtualProtocol<TDenseProtocol, TBinaryProtocol>::readBool;
uint32_t readByte(int8_t& byte);
diff --git a/lib/cpp/src/protocol/TJSONProtocol.h b/lib/cpp/src/protocol/TJSONProtocol.h
index b3a6667..2be54da 100644
--- a/lib/cpp/src/protocol/TJSONProtocol.h
+++ b/lib/cpp/src/protocol/TJSONProtocol.h
@@ -243,6 +243,9 @@
uint32_t readBool(bool& value);
+ // Provide the default readBool() implementation for std::vector<bool>
+ using TVirtualProtocol<TJSONProtocol>::readBool;
+
uint32_t readByte(int8_t& byte);
uint32_t readI16(int16_t& i16);
diff --git a/lib/cpp/src/protocol/TProtocol.h b/lib/cpp/src/protocol/TProtocol.h
index 4b05de2..3c06bf5 100644
--- a/lib/cpp/src/protocol/TProtocol.h
+++ b/lib/cpp/src/protocol/TProtocol.h
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <string>
#include <map>
+#include <vector>
// Use this to get around strict aliasing rules.
@@ -493,6 +494,8 @@
virtual uint32_t readBool_virt(bool& value) = 0;
+ virtual uint32_t readBool_virt(std::vector<bool>::reference value) = 0;
+
virtual uint32_t readByte_virt(int8_t& byte) = 0;
virtual uint32_t readI16_virt(int16_t& i16) = 0;
@@ -611,11 +614,14 @@
return readBinary_virt(str);
}
- uint32_t readBool(std::vector<bool>::reference ref) {
- bool value;
- uint32_t rv = readBool(value);
- ref = value;
- return rv;
+ /*
+ * std::vector is specialized for bool, and its elements are individual bits
+ * rather than bools. We need to define a different version of readBool()
+ * to work with std::vector<bool>.
+ */
+ uint32_t readBool(std::vector<bool>::reference value) {
+ T_VIRTUAL_CALL();
+ return readBool_virt(value);
}
/**
diff --git a/lib/cpp/src/protocol/TProtocolTap.h b/lib/cpp/src/protocol/TProtocolTap.h
index 26fbd3a..3772bff 100644
--- a/lib/cpp/src/protocol/TProtocolTap.h
+++ b/lib/cpp/src/protocol/TProtocolTap.h
@@ -133,6 +133,9 @@
return rv;
}
+ // Provide the default readBool() implementation for std::vector<bool>
+ using TVirtualProtocol<TProtocolTap>::readBool;
+
uint32_t readByte(int8_t& byte) {
uint32_t rv = source_->readByte(byte);
sink_->writeByte(byte);
diff --git a/lib/cpp/src/protocol/TVirtualProtocol.h b/lib/cpp/src/protocol/TVirtualProtocol.h
index 7f01570..9133dbe 100644
--- a/lib/cpp/src/protocol/TVirtualProtocol.h
+++ b/lib/cpp/src/protocol/TVirtualProtocol.h
@@ -108,6 +108,11 @@
"this protocol does not support reading (yet).");
}
+ uint32_t readBool(std::vector<bool>::reference value) {
+ throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
+ "this protocol does not support reading (yet).");
+ }
+
uint32_t readByte(int8_t& byte) {
throw TProtocolException(TProtocolException::NOT_IMPLEMENTED,
"this protocol does not support reading (yet).");
@@ -437,6 +442,10 @@
return static_cast<Protocol_*>(this)->readBool(value);
}
+ virtual uint32_t readBool_virt(std::vector<bool>::reference value) {
+ return static_cast<Protocol_*>(this)->readBool(value);
+ }
+
virtual uint32_t readByte_virt(int8_t& byte) {
return static_cast<Protocol_*>(this)->readByte(byte);
}
@@ -484,6 +493,21 @@
return ::apache::thrift::protocol::skip(*prot, type);
}
+ /*
+ * Provide a default readBool() implementation for use with
+ * std::vector<bool>, that behaves the same as reading into a normal bool.
+ *
+ * Subclasses can override this if desired, but there normally shouldn't
+ * be a need to.
+ */
+ uint32_t readBool(std::vector<bool>::reference value) {
+ bool b = false;
+ uint32_t ret = static_cast<Protocol_*>(this)->readBool(b);
+ value = b;
+ return ret;
+ }
+ using Super_::readBool; // so we don't hide readBool(bool&)
+
protected:
TVirtualProtocol(boost::shared_ptr<TTransport> ptrans)
: Super_(ptrans)