Skip to content

Commit 53c8e2c

Browse files
authored
Issue 1066 (#1080)
Implemented `as<T>()` and `is<T>()` with accompanying tests
1 parent 645cd04 commit 53c8e2c

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

include/json/value.h

+39
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,10 @@ class JSON_API Value {
412412
bool isArray() const;
413413
bool isObject() const;
414414

415+
/// The `as<T>` and `is<T>` member function templates and specializations.
416+
template <typename T> T as() const = delete;
417+
template <typename T> bool is() const = delete;
418+
415419
bool isConvertibleTo(ValueType other) const;
416420

417421
/// Number of values in array or object
@@ -673,6 +677,41 @@ class JSON_API Value {
673677
ptrdiff_t limit_;
674678
};
675679

680+
template <> inline bool Value::as<bool>() const { return asBool(); }
681+
template <> inline bool Value::is<bool>() const { return isBool(); }
682+
683+
template <> inline Int Value::as<Int>() const { return asInt(); }
684+
template <> inline bool Value::is<Int>() const { return isInt(); }
685+
686+
template <> inline UInt Value::as<UInt>() const { return asUInt(); }
687+
template <> inline bool Value::is<UInt>() const { return isUInt(); }
688+
689+
#if defined(JSON_HAS_INT64)
690+
template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
691+
template <> inline bool Value::is<Int64>() const { return isInt64(); }
692+
693+
template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
694+
template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
695+
#endif
696+
697+
template <> inline double Value::as<double>() const { return asDouble(); }
698+
template <> inline bool Value::is<double>() const { return isDouble(); }
699+
700+
template <> inline String Value::as<String>() const { return asString(); }
701+
template <> inline bool Value::is<String>() const { return isString(); }
702+
703+
/// These `as` specializations are type conversions, and do not have a
704+
/// corresponding `is`.
705+
template <> inline float Value::as<float>() const { return asFloat(); }
706+
template <> inline const char* Value::as<const char*>() const {
707+
return asCString();
708+
}
709+
#ifdef JSON_USE_CPPTL
710+
template <> inline CppTL::ConstString Value::as<CppTL::ConstString>() const {
711+
return asConstString();
712+
}
713+
#endif
714+
676715
/** \brief Experimental and untested: represents an element of the "path" to
677716
* access a node.
678717
*/

src/test_lib_json/main.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -3502,6 +3502,53 @@ int main(int argc, const char* argv[]) {
35023502
return runner.runCommandLine(argc, argv);
35033503
}
35043504

3505+
struct MemberTemplateAs : JsonTest::TestCase {
3506+
template <typename T, typename F>
3507+
JsonTest::TestResult& EqEval(T v, F f) const {
3508+
const Json::Value j = v;
3509+
return JSONTEST_ASSERT_EQUAL(j.as<T>(), f(j));
3510+
}
3511+
};
3512+
3513+
JSONTEST_FIXTURE_LOCAL(MemberTemplateAs, BehavesSameAsNamedAs) {
3514+
const Json::Value jstr = "hello world";
3515+
JSONTEST_ASSERT_STRING_EQUAL(jstr.as<const char*>(), jstr.asCString());
3516+
JSONTEST_ASSERT_STRING_EQUAL(jstr.as<Json::String>(), jstr.asString());
3517+
#ifdef JSON_USE_CPPTL
3518+
JSONTEST_ASSERT_STRING_EQUAL(js.as<CppTL::ConstString>(), js.asConstString());
3519+
#endif
3520+
EqEval(Json::Int(64), [](const Json::Value& j) { return j.asInt(); });
3521+
EqEval(Json::UInt(64), [](const Json::Value& j) { return j.asUInt(); });
3522+
#if defined(JSON_HAS_INT64)
3523+
EqEval(Json::Int64(64), [](const Json::Value& j) { return j.asInt64(); });
3524+
EqEval(Json::UInt64(64), [](const Json::Value& j) { return j.asUInt64(); });
3525+
#endif // if defined(JSON_HAS_INT64)
3526+
EqEval(Json::LargestInt(64),
3527+
[](const Json::Value& j) { return j.asLargestInt(); });
3528+
EqEval(Json::LargestUInt(64),
3529+
[](const Json::Value& j) { return j.asLargestUInt(); });
3530+
3531+
EqEval(69.69f, [](const Json::Value& j) { return j.asFloat(); });
3532+
EqEval(69.69, [](const Json::Value& j) { return j.asDouble(); });
3533+
EqEval(false, [](const Json::Value& j) { return j.asBool(); });
3534+
EqEval(true, [](const Json::Value& j) { return j.asBool(); });
3535+
}
3536+
3537+
class MemberTemplateIs : public JsonTest::TestCase {};
3538+
3539+
JSONTEST_FIXTURE_LOCAL(MemberTemplateIs, BehavesSameAsNamedIs) {
3540+
const Json::Value values[] = {true, 142, 40.63, "hello world"};
3541+
for (const Json::Value& j : values) {
3542+
JSONTEST_ASSERT_EQUAL(j.is<bool>(), j.isBool());
3543+
JSONTEST_ASSERT_EQUAL(j.is<Json::Int>(), j.isInt());
3544+
JSONTEST_ASSERT_EQUAL(j.is<Json::Int64>(), j.isInt64());
3545+
JSONTEST_ASSERT_EQUAL(j.is<Json::UInt>(), j.isUInt());
3546+
JSONTEST_ASSERT_EQUAL(j.is<Json::UInt64>(), j.isUInt64());
3547+
JSONTEST_ASSERT_EQUAL(j.is<double>(), j.isDouble());
3548+
JSONTEST_ASSERT_EQUAL(j.is<Json::String>(), j.isString());
3549+
}
3550+
}
3551+
35053552
#if defined(__GNUC__)
35063553
#pragma GCC diagnostic pop
35073554
#endif

0 commit comments

Comments
 (0)