Skip to content

Commit

Permalink
Add cpp:custom-print for classes
Browse files Browse the repository at this point in the history
  • Loading branch information
bernardnormier committed Jan 17, 2025
1 parent 169a066 commit d9a8a28
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 9 deletions.
24 changes: 16 additions & 8 deletions cpp/include/Ice/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,10 @@ namespace Ice
*/
[[nodiscard]] SlicedDataPtr ice_getSlicedData() const;

/**
* Outputs a description of this instance to the stream. This description includes the type name and the name
* and value of all the fields of this instance.
* @param os The output stream.
*/
/// Outputs a description of this instance to the stream. This description includes the type name and the name
/// and value of all the fields of this instance.
/// Use ["cpp:custom-print"] to tell the Slice compiler to generate an override implemented by the application.
/// @param os The output stream.
virtual void ice_print(std::ostream& os) const;

/// Outputs the name and value of each field of this instance, including inherited fields, to the stream.
Expand Down Expand Up @@ -111,8 +110,17 @@ namespace Ice
SlicedDataPtr _slicedData;
};

/// Outputs the description of a class instance to the stream by calling the ice_print member function when this
/// instance is not null.
/// Outputs the description of a class instance to the stream. This function calls ice_print on value.
/// @param os The output stream.
/// @param value The class instance.
/// @return The output stream.
inline std::ostream& operator<<(std::ostream& os, const Value& value)
{
value.ice_print(os);
return os;
}

/// Outputs the description of a class instance held in a shared_ptr.
/// @tparam T The class type.
/// @param os The output stream.
/// @param value The class instance held in a shared pointer. May be null.
Expand All @@ -122,7 +130,7 @@ namespace Ice
{
if (value)
{
value->ice_print(os);
os << *value;
}
else
{
Expand Down
9 changes: 8 additions & 1 deletion cpp/src/slice2cpp/Gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ Slice::Gen::validateMetadata(const UnitPtr& u)

// "cpp:custom-print"
MetadataInfo customPrintInfo = {
.validOn = {typeid(Struct)},
.validOn = {typeid(Struct), typeid(ClassDecl)},
.acceptedArgumentKind = MetadataArgumentKind::NoArguments,
};
knownMetadata.emplace("cpp:custom-print", std::move(customPrintInfo));
Expand Down Expand Up @@ -2334,6 +2334,13 @@ Slice::Gen::DataDefVisitor::visitClassDefEnd(const ClassDefPtr& p)
emitDataMember(dataMember);
}

if (p->hasMetadata("cpp:custom-print"))
{
H << sp;
H << nl << "// Custom ice_print implemented by the application.";
H << nl << "void ice_print(std::ostream& os) const override;";
}

const string baseClass = base ? getUnqualified(base->mappedScoped(), scope) : getUnqualified("::Ice::Value", scope);

if (!dataMembers.empty())
Expand Down
22 changes: 22 additions & 0 deletions cpp/test/Ice/print/AllTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
using namespace std;
using namespace Test;

void
Test::Neighbor::ice_print(ostream& os) const
{
os << name;
if (age)
{
os << " (" << *age << ")";
}
os << " @ " << address;
}

template<class T>
void
testPrint(const T& value, const string& expected, std::optional<int> floatPrecision = std::nullopt)
Expand Down Expand Up @@ -91,6 +102,16 @@ testClass()
"= []}");
}

void
testClassCustomPrint()
{
auto neighbor = make_shared<Neighbor>("Alice", 30, "123 Main St");
testPrint(neighbor, "Alice (30) @ 123 Main St");

// This works too:
testPrint(*neighbor, "Alice (30) @ 123 Main St");
}

void
allTests(Test::TestHelper*)
{
Expand All @@ -99,4 +120,5 @@ allTests(Test::TestHelper*)
testCustomStruct();
testDictionaryStruct();
testClass();
testClassCustomPrint();
}
6 changes: 6 additions & 0 deletions cpp/test/Ice/print/Test.ice
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,10 @@ module Test
Employee manager;
EmployeeSeq directReports;
}

["cpp:custom-print"]
class Neighbor extends Person
{
string address;
}
}

0 comments on commit d9a8a28

Please sign in to comment.