From 8dfc732af635d5243194b74d4f411a551ff9a5ee Mon Sep 17 00:00:00 2001 From: David Reiss Date: Wed, 6 Oct 2010 17:09:58 +0000 Subject: [PATCH] THRIFT-922. cpp: Fix C++ compilation when using list The STL specializes vector to store the values as individual bits, rather than bools. Therefore, when using a Thrift list, readBool() gets invoked not with a bool&, but with a std::vector::reference. TProtocol does provide a readBool(std::vector::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 is used. This change updates the various TProtocol implementations to also provide readBool(std::vector::reference). git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@1005137 13f79535-47bb-0310-9956-ffa450edef68 --- lib/cpp/src/protocol/TBinaryProtocol.h | 2 ++ lib/cpp/src/protocol/TCompactProtocol.h | 2 ++ lib/cpp/src/protocol/TDenseProtocol.h | 2 ++ lib/cpp/src/protocol/TJSONProtocol.h | 3 +++ lib/cpp/src/protocol/TProtocol.h | 16 +++++++++++----- lib/cpp/src/protocol/TProtocolTap.h | 3 +++ lib/cpp/src/protocol/TVirtualProtocol.h | 24 ++++++++++++++++++++++++ 7 files changed, 47 insertions(+), 5 deletions(-) diff --git a/lib/cpp/src/protocol/TBinaryProtocol.h b/lib/cpp/src/protocol/TBinaryProtocol.h index ca45294e..edb8834f 100644 --- a/lib/cpp/src/protocol/TBinaryProtocol.h +++ b/lib/cpp/src/protocol/TBinaryProtocol.h @@ -174,6 +174,8 @@ class TBinaryProtocolT inline uint32_t readSetEnd(); inline uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< TBinaryProtocolT >::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 2150cde9..19a0160a 100644 --- a/lib/cpp/src/protocol/TCompactProtocol.h +++ b/lib/cpp/src/protocol/TCompactProtocol.h @@ -192,6 +192,8 @@ class TCompactProtocolT uint32_t& size); uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< TCompactProtocolT >::readBool; uint32_t readByte(int8_t& byte); diff --git a/lib/cpp/src/protocol/TDenseProtocol.h b/lib/cpp/src/protocol/TDenseProtocol.h index ca2d4273..438ed891 100644 --- a/lib/cpp/src/protocol/TDenseProtocol.h +++ b/lib/cpp/src/protocol/TDenseProtocol.h @@ -189,6 +189,8 @@ class TDenseProtocol uint32_t readSetEnd(); uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; uint32_t readByte(int8_t& byte); diff --git a/lib/cpp/src/protocol/TJSONProtocol.h b/lib/cpp/src/protocol/TJSONProtocol.h index b3a66679..2be54da2 100644 --- a/lib/cpp/src/protocol/TJSONProtocol.h +++ b/lib/cpp/src/protocol/TJSONProtocol.h @@ -243,6 +243,9 @@ class TJSONProtocol : public TVirtualProtocol { uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::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 4b05de20..3c06bf5c 100644 --- a/lib/cpp/src/protocol/TProtocol.h +++ b/lib/cpp/src/protocol/TProtocol.h @@ -30,6 +30,7 @@ #include #include #include +#include // Use this to get around strict aliasing rules. @@ -493,6 +494,8 @@ class TProtocol { virtual uint32_t readBool_virt(bool& value) = 0; + virtual uint32_t readBool_virt(std::vector::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 @@ class TProtocol { return readBinary_virt(str); } - uint32_t readBool(std::vector::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. + */ + uint32_t readBool(std::vector::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 26fbd3ab..3772bff5 100644 --- a/lib/cpp/src/protocol/TProtocolTap.h +++ b/lib/cpp/src/protocol/TProtocolTap.h @@ -133,6 +133,9 @@ class TProtocolTap : public TVirtualProtocol { return rv; } + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::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 7f015706..9133dbed 100644 --- a/lib/cpp/src/protocol/TVirtualProtocol.h +++ b/lib/cpp/src/protocol/TVirtualProtocol.h @@ -108,6 +108,11 @@ class TProtocolDefaults : public TProtocol { "this protocol does not support reading (yet)."); } + uint32_t readBool(std::vector::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 @@ class TVirtualProtocol : public Super_ { return static_cast(this)->readBool(value); } + virtual uint32_t readBool_virt(std::vector::reference value) { + return static_cast(this)->readBool(value); + } + virtual uint32_t readByte_virt(int8_t& byte) { return static_cast(this)->readByte(byte); } @@ -484,6 +493,21 @@ class TVirtualProtocol : public Super_ { return ::apache::thrift::protocol::skip(*prot, type); } + /* + * Provide a default readBool() implementation for use with + * std::vector, 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::reference value) { + bool b = false; + uint32_t ret = static_cast(this)->readBool(b); + value = b; + return ret; + } + using Super_::readBool; // so we don't hide readBool(bool&) + protected: TVirtualProtocol(boost::shared_ptr ptrans) : Super_(ptrans) -- 2.17.1