Struct composition with mixin and templates - templates

I can compose an AB struct that has all the members of structs A and B:
template AFields() {int a;}
struct A { mixin AFields; }
template BFields() {int b;}
struct B { mixin BFields; }
struct AB { mixin AFields; mixin BFields; }
A a; a.a = 1;
B b; b.b = 2;
AB ab; ab.a = 3; ab.b = 4;
But how can I construct AB, if I don't have control over A and B and I don't have AFields and BFields? I.e. how to write the CatStruct template so the code below compiles?
struct A { int a; }
struct B { int b; }
mixin CatStruct!("AB", A, B);
AB ab;
ab.a = 1; ab.b = 2;

The standard library has a few hidden jewels that I didn't actually even know about myself until I peeked at the source to answer this question:
http://dlang.org/phobos/std_traits.html#Fields
and the ones right under it too. With these, we can make your CatStruct fairly succinctly. Behold:
mixin template CatStruct(string name, T...) {
static import std.traits, std.conv;
private string _code_generator() {
string code = "struct " ~ name ~ " {";
foreach(oidx, t; T) {
foreach(idx, field; std.traits.FieldTypeTuple!t)
// this line is a monster, see the end of this answer
code ~= "std.traits.FieldTypeTuple!(T["~std.conv.to!string(oidx)~"])["~std.conv.to!string(idx)~"] "~ std.traits.FieldNameTuple!t[idx] ~ ";";
}
code ~= "}";
return code;
}
mixin(_code_generator());
}
This uses a string mixin though... and while string mixins can do basically anything, they also basically suck. This is liable to be brittle but I think it will basically work while basically sucking.
It also won't do struct methods, but I think that's too hard to realistically do with any of these magical things, except perhaps opDispatch, as seen in the other answer (which is pretty nice btw, don't take my answer as a repudiation of that one, just another idea).
If there's clashing names between the two structs too, they will break this, and you will get a hideously ugly error message out of the compiler. With a real template mixin, there's an easy fix for that - a named template mixin, which allows you to disambiguate. But no such thing here. I guess you could hack one in if you needed it.
But anyway, there might be a way to use those FieldTypeTuple and FieldNameTuple from the stdlib to do this even nicer, but I think it is more-or-less what you're asking for now.
BTW, I'd say just do ordinary composition if you at all can, it is going to work the best in general. (Don't forget about alias this too which can do automatic forwarding to member variables.)
If you haven't done a lot of mixins, you probably want to ask my why I used that crazy string in the code ~= part instead of the more straightforward. code ~= field.stringof ~ " "~ FieldNameTuple!t[idx] ~ ";";
tl;dr: just trust me, ALWAYS use local names available to the scope where you run the mixin() itself in the code you generate. Long explanation follows/
It has to do with name clashes and symbol lookups. I used static imports and fully qualified names in the mixed in code - including using the local symbol for the FieldTypeTuple rather than field.stringof - to keep this as namespace-tidy as possible.
Consider the case where struct A imports some other module internally and defines a field with it.
// using my color.d just cuz I have it easily available
// but it could be anything, so don't worry about downloading it
struct A { import arsd.color; Color a; }
AB ab;
import arsd.color;
ab.a = Color.white; ab.b = 2; // we expect this work, should be the same type
Since that's a local import inside struct A, the name is meaningless at the point of the mixin.
Go ahead and adjust the mixin so it compiles using the simple line
// comment fancy line
// code ~= "std.traits.FieldTypeTuple!(T["~std.conv.to!string(oidx)~"])["~std.conv.to!string(idx)~"] "~ std.traits.FieldNameTuple!t[idx] ~ ";";
// paste in simple line
code ~= field.stringof ~ " "~ std.traits.FieldNameTuple!t[idx] ~ ";";
And compile:
$ dmd f.d ~/arsd/color.d
f.d-mixin-31(31): Error: undefined identifier 'Color'
f.d(4): Error: mixin f.CatStruct!("AB", A, B) error instantiating
Zoinks! It had no idea what the string "Color" was supposed to refer to. If we imported some other kind of struct Color in the local module, it would compile.... but then it would refer to a different type:
struct A { import arsd.color; Color a; }
struct B { int b; }
struct Color { static Color white() { return Color.init; } }
mixin CatStruct!("AB", A, B);
AB ab;
import arsd.color;
ab.a = Color.white; ab.b = 2;
Compile it and see a silly sounding error:
$ dmd f.d ~/arsd/color.d
f.d(12): Error: cannot implicitly convert expression (white()) of type Color to Color
BTW: remember this if you ever see it in the wild - the compiler error message sounds absurd, "cannot implicitly convert Color to Color", but it actually does have a logical meaning: there's just two different types with the same name in different modules.
Anyway, it sounds silly, but makes sense because the two scopes imported different structs.
With the long-form FieldTypeTuple used with a local static import, it always refers to the actual type passed in. Indirectly, sure, but also unambiguously.
I apologize to those reading this who already know about the pitfalls of string mixins, but anyone finding this on a search might not know why I used that convoluted code. It is complex due to real world experience with actual problems, I swear! :) It is a lot easier to do it right the first time than try to debug the weird nonsense down the road it can bring doing it the other way.

There's a lot of ground to cover here (members, functions, templates, ect.).
However, here's an idea to get you started:
import std.typecons;
struct A { int a; }
struct B { int b; }
struct AB
{
mixin MultiProxy!(A, B);
}
mixin template MultiProxy(A, B) {
private A _a;
private B _b;
mixin Proxy!_a aProxy;
mixin Proxy!_b bProxy;
template opDispatch(string op) {
static if (is(typeof(aProxy.opDispatch!op))) {
alias opDispatch = aProxy.opDispatch!op;
}
else {
alias opDispatch = bProxy.opDispatch!op;
}
}
}
unittest
{
AB ab;
ab.a = 4;
ab.b = 5;
assert(ab.a == 4);
assert(ab.b == 5);
}
I haven't had time to thoroughly test this, so I wouldn't be suprised if there are a number of areas where it falls over (just look at the implementation of Proxy to see all the things it has to take into account).
However, the general idea is to create two proxies, each explicitly named (aProxy,bProxy) so we can explicitly call the opDispatch of either one depending on which will compile.

In the interest of completeness, here's a solution that uses named tuples:
import std.meta, std.traits, std.typecons;
// helper template to interleave 2 alias lists
template Interleave(A...)
{
static if(A.length == 0)
alias A Interleave;
else
alias AliasSeq!(A[0], A[A.length/2],
Interleave!(A[1..A.length/2], A[A.length/2+1..$])) Interleave;
}
// helper template to produce tuple template parameters
template FieldTypeNameTuple(A)
{
alias Interleave!(Fields!A, FieldNameTuple!A) FieldTypeNameTuple;
}
template CatStruct(A...)
{
alias Tuple!(staticMap!(FieldTypeNameTuple, A)) CatStruct;
}
// usage
struct A { int a; }
struct B { int b; }
struct C { int c; }
alias CatStruct!(A, B, C) ABC;

Related

Customizable way to instantiate objects in 1 expression in C++

In Rust, there is this crate which utilize Rust procedural macro to automatically implement builder pattern for any arbitrary struct defined. As there is no flexible way to instantiate Rust struct with some default and some provided values, this helps a lot in reducing boilerplate.
Is there any similar thing to generate builders automatically in C++, as instantiating objects in C++ also requires a lot of boilerplate (a lot of overloaded constructors to cover all posible combinations of fields or multiple steps initialization), possibly using C/C++ macros?
As the comments suggested, I added an example to clarify my idea. I want to instantiate class A below by just provide some field I want and leave others as default. If so, I either have to implement a lot of constructors or do multiple steps, instantiate and then override fields I want:
Multiple constructors
#include <string>
#include <iostream>
class A
{
public:
int a = 2;
std::string b = "b";
int c = 5;
std::string d = "d";
A() {}
A(int a) { this->a = a; }
A(std::string b) { this->b = b; }
A(int a, std::string b)
{
this->a = a;
this->b = b;
}
// ... more constructors to cover all combinations
// this might not even work as some combinations might
// have similar types, which prevent overloading them
};
Multiple steps
A a;
a.b = "hello";
a.c = 10;
Multiple steps instantiation is actually nice. However, it does not work if I want to have customized instantiation in 1 expression.
With builder pattern, I do that in 1 expression by chaining methods like this:
BuilderOfA()
.a(7)
.c(8)
.build();
Can the definition of this builder be automatically generated at compile time in C++? If not, is there anyway I can instantiate an object in a customizable way (by just provide some field I want and leave others as default) without using multiple expressions?
In c++ 20 you can do this:
struct S {
std::string str = "Hello";
float y = 1.0f;
int x = 10;
};
auto a = S{ .str = "Hi", .x = 8 };

Understanding mixins vs mixin templates

In the process of learning the D language, I'm trying to make a generic Matrix class which supports type promotion of the contained object.
That is, when I multiply a Matrix!(int) to a Matrix!(real) I should get a Matrix!(real) as a result.
Since there are many different kinds of type promotions, reimplementing the opBinary method for every possible combination would be really tedious and a ton of boilerplate code. So mixins/mixin templates would seem to be the answer.
What I'm failing to understand is why this first code sample works
import std.stdio;
import std.string : format;
string define_opbinary(string other_type) {
return "
Matrix opBinary(string op)(Matrix!(%s) other) {
if(op == \"*\") {
Matrix result;
if(this.columns == other.rows) {
result = new Matrix(this.rows, other.columns);
} else {
result = new Matrix(0,0);
}
return result;
} else assert(0, \"Operator \"~op~\" not implemented\");
}
".format(other_type);
}
class Matrix(T) {
T[][] storage;
size_t rows;
size_t columns;
const string type = T.stringof;
this(size_t rows, size_t columns) {
this.storage = new T[][](rows, columns);
this.rows = rows;
this.columns = columns;
}
void opIndexAssign(T value, size_t row, size_t column) {
storage[row][column] = value;
}
mixin(define_opbinary(int.stringof));
mixin(define_opbinary(uint.stringof));
}
void main()
{
Matrix!int mymat = new Matrix!(int)(2, 2);
mymat[0,0] = 5;
writeln(mymat.type);
Matrix!uint mymat2 = new Matrix!(uint)(2, 2);
writeln(mymat2.type);
auto result = mymat * mymat2;
writeln("result.rows=", result.rows);
writeln("result.columns=", result.columns);
auto result2 = mymat2 * mymat;
writeln("result.type=",result.type);
writeln("result2.type=",result2.type);
}
the dub output:
Performing "debug" build using /usr/bin/dmd for x86_64.
matrix ~master: building configuration "application"...
Linking...
Running ./matrix.exe
50
00
int
uint
result.rows=2
result.columns=2
00
00
result.type=int
result2.type=uint
but the second code sample does not work
import std.stdio;
import std.string : format;
mixin template define_opbinary(alias other_type) {
Matrix opBinary(string op)(Matrix!(other_type) other) {
if(op == "*") {
Matrix result;
if(this.columns == other.rows) {
result = new Matrix(this.rows, other.columns);
} else {
result = new Matrix(0,0);
}
return result;
} else assert(0, "Operator "~op~" not implemented");
}
}
class Matrix(T) {
T[][] storage;
size_t rows;
size_t columns;
const string type = T.stringof;
this(size_t rows, size_t columns) {
this.storage = new T[][](rows, columns);
this.rows = rows;
this.columns = columns;
}
void opIndexAssign(T value, size_t row, size_t column) {
storage[row][column] = value;
}
mixin define_opbinary!(int);
mixin define_opbinary!(uint);
}
void main()
{
Matrix!int mymat = new Matrix!(int)(2, 2);
mymat[0,0] = 5;
writeln(mymat.type);
Matrix!uint mymat2 = new Matrix!(uint)(2, 2);
writeln(mymat2.type);
auto result = mymat * mymat2;
writeln("result.rows=", result.rows);
writeln("result.columns=", result.columns);
auto result2 = mymat2 * mymat;
writeln("result.type=",result.type);
writeln("result2.type=",result2.type);
}
the dub output:
source/app.d(60,19): Error: cast(Object)mymat is not of arithmetic type, it is a object.Object
source/app.d(60,27): Error: cast(Object)mymat2 is not of arithmetic type, it is a object.Object
source/app.d(64,20): Error: cast(Object)mymat2 is not of arithmetic type, it is a object.Object
source/app.d(64,29): Error: cast(Object)mymat is not of arithmetic type, it is a object.Object
/usr/bin/dmd failed with exit code 1.
What's extremely odd is that if I remove the mixin define_opbinary!(int); call, then I only get two arithmetic complaints (only the two complaints about line 60 (auto result = mymat * mymat2;) remain).
I have a feeling that somehow the compiler sees the two mixin calls as ambiguous and removes both but I'm not sure.
Any help would be greatly appreciated.
Oh I have a lot to say about this, including that I wouldn't use either type of mixin for this - I'd just use an ordinary template instead. I'll come back to that at the end.
I am going to try to be fairly comprehensive, so apologies if I describe stuff you already know, and on the other hand, I am probably going to give some irrelevant material too in the interests of providing comprehensive background material for a deeper understanding.
First, mixin vs template mixin. mixin() takes a string, parses it into a AST node (the AST btw is the compiler's internal data structure for representing code, it stands for "abstract syntax tree". foo() is an AST node like FunctionCall { args: [] }. if(foo) {} is one like IfStatement { condition: Expression { arg: Variable { name: foo }, body : EmptyStatement } - basically objects representing each part of the code).
Then it pastes that parsed AST node into the same slot where the mixin word appeared. You can often think of this as copy/pasting code strings, but with the restriction that the string must represent a complete element here, and it must be substituteable in the same context where the mixin was without errors. So like you can't do int a = bmixin(c) to make a variable with a b in front - the mixin must represent a complete node by itself.
Once it pastes in that AST node though, the compiler treats it as if the code was all written there originally. Any names referenced will be looked up in the pasted context, etc.
A template mixin, on the other hand, actually still has a container element in the AST, which is used for name lookups. It actually works similarly to a struct or class inside the compiler - they all have a list of child declarations that remain together as a unit.
The big difference is that a template mixin's contents are automatically accessible from the parent context... usually. It follows rules similar to class inheritance, where class Foo : Bar can see Bar's members as if they are its own, but they still remain separate. You can still do like super.method(); and call it independently of the child's overrides.
The "usually" comes in because of overloading and hijacking rules. Deep dive and rationale here: https://dlang.org/articles/hijack.html
But the short of it is in an effort to prevent third party code from silently being able to change your program's behavior when they add a new function, D requires all sets of function overloads to be merged at the usage point by the programmer, and it is particularly picky about operator overloads since they already have a default behavior that any mixin is going to be modifying.
mixin template B(T) {
void foo(T t) {}
}
class A {
mixin B!int;
mixin B!string;
}
This is similar to the code you have, but with an ordinary function. If you compile and run, it will work. Now, let's add a foo overload directly to A:
mixin template B(T) {
void foo(T t) {}
}
class A {
mixin B!int;
mixin B!string;
void foo(float t) {}
}
If you try to compile this with a string argument, it will actually fail! "Error: function poi.A.foo(float t) is not callable using argument types (string)". Why won't it use the mixin one?
This is a rule of template mixins - remember the compiler still treats them as a unit, not just a pasted set of declarations. Any name present on the outer object - here, our class A - will be used instead of looking inside the template mixin.
Hence, it sees A.foo and doesn't bother looking into B to find a foo. This is kinda useful for overriding specific things from a template mixin, but can be a hassle when trying to add overloads. The solution is to add an alias line to the top-level to tell the compiler to specifically look inside. First, we need to give the mixin a name, then forward the name explicitly:
mixin template B(T) {
void foo(T t) {}
}
class A {
mixin B!int bint; // added a name here
mixin B!string bstring; // and here
alias foo = bint.foo; // forward foo to the template mixin
alias foo = bstring.foo; // and this one too
void foo(float t) {}
}
void main() {
A a = new A;
a.foo("a");
}
Now it works for float, int, and string.... but it also kinda defeats the purpose of template mixins for adding overloads. One trick you can to is to put a top-level template function in A, and it just forwards to the mixins... just they need a different name to register.
Which brings me back to your code. Like I said, D is particularly picky about operator overloads since they always override a normal behavior (even when that normal behavior is an error, like in classes). You need to be explicit about them at the top level.
Consider the following:
import std.stdio;
import std.string : format;
mixin template define_opbinary(alias other_type) {
// I renamed this to opBinaryHelper since it will not be used directly
// but rather called from the top level
Matrix opBinaryHelper(string op)(Matrix!(other_type) other) {
if(op == "*") {
Matrix result;
if(this.columns == other.rows) {
result = new Matrix(this.rows, other.columns);
} else {
result = new Matrix(0,0);
}
return result;
} else assert(0, "Operator "~op~" not implemented");
}
}
class Matrix(T) {
T[][] storage;
size_t rows;
size_t columns;
const string type = T.stringof;
this(size_t rows, size_t columns) {
this.storage = new T[][](rows, columns);
this.rows = rows;
this.columns = columns;
}
void opIndexAssign(T value, size_t row, size_t column) {
storage[row][column] = value;
}
mixin define_opbinary!(int);
mixin define_opbinary!(uint);
// and now here, we do a top-level opBinary that calls the helper
auto opBinary(string op, M)(M rhs) {
return this.opBinaryHelper!(op)(rhs);
}
}
void main()
{
Matrix!int mymat = new Matrix!(int)(2, 2);
mymat[0,0] = 5;
writeln(mymat.type);
Matrix!uint mymat2 = new Matrix!(uint)(2, 2);
writeln(mymat2.type);
auto result = mymat * mymat2;
writeln("result.rows=", result.rows);
writeln("result.columns=", result.columns);
auto result2 = mymat2 * mymat;
writeln("result.type=",result.type);
writeln("result2.type=",result2.type);
}
I pasted in the complete code, but there's actually only two changes there: the mixin template now defines a helper with a different name (opBinaryHelper), and the top-level class now has an explicit opBinary defined that forwards to said helper. (If you were to add other overloads btw, the alias trick from above may be necessary, but in this case, since it is all dispatched on if from inside the one name, it lets you merge all the helpers automatically.)
Finally, the code works.
Now, why wasn't any of this necessary with the string mixin? Well, back to the original definition: a string mixin parses it, then pastes in the AST node /as if it were originally written there/. That latter part lets it work (just at the cost of once you mixin a string, you are stuck with it, so if you don't like part of it, you must modify the library instead of just overriding a portion).
A template mixin maintains its own sub-namespace to allow for selective overriding, etc., and that triggers a foul with these stricter overloading rules.
And finally, here's the way I'd actually do it:
// this MatrixType : stuff magic means to accept any Matrix, and extract
// the other type out of it.
// a little docs: https://dlang.org/spec/template.html#alias_parameter_specialization
// basically, write a pattern that represents the type, then comma-separate
// a list of placeholders you declared in that pattern
auto opBinary(string op, MatrixType : Matrix!Other_Type, Other_Type)(MatrixType other) {
// let the compiler do the promotion work for us!
// we just fetch the type of regular multiplication between the two types
// the .init just uses the initial default value of the types as a placeholder,
// all we really care about is the type, just can't multiply types, only
// values hence using that.
alias PromotedType = typeof(T.init * Other_Type.init);
// in your version, you used `if`, but since this is a compile-time
// parameter, we can use `static if` instead and get more flexibility
// on stuff like actually changing the return value per operation.
//
// Don't need it here, but wanted to point it out anyway.
static if(op == "*") {
// and now use that type for the result
Matrix!PromotedType result;
if(this.columns == other.rows) {
result = new Matrix!PromotedType(this.rows, other.columns);
} else {
result = new Matrix!PromotedType(0,0);
}
return result;
// and with static if, we can static assert to turn that runtime
// exception into a compile-time error
} else static assert(0, "Operator "~op~" not implemented");
}
Just put that opBinary in your class and now the one function can handle all the cases - no need to list specific types, so no more need for mixin magic at all! (....well unless you need virtual overriding with child classes, but that's a whole other topic. Short tip tho, it is possible to static foreach that, which I talked about in my last SO answer here: https://stackoverflow.com/a/57599398/1457000 )
There's a few D tricks in that little function, but I tried to explain in the comments of the code. Feel free to ask if you need more clarification though - those : patterns in template are IMO one of the more advanced D compile-time reflection things, so they're not easy to get at first, but for simple cases like this, it kinda makes sense, just think of it as a declaration with placeholders.

Using initialized variable after placement new from the constructor tripping UB?

Disregarding whether the following can be achieved through other, more safe constructs - I'm simply interested in whether or not the following results in a well-defined output.
Assume you have a struct A:
struct A {
Foo* foo;
}
And a struct B inheriting from it:
struct B : A {
B() {
foo->some_function(); // UB
}
}
Sure enough if you were creating a B instance the normal way you'd trip UB, however...
template<typename R>
R make_A() { // This acts like a constructor for As
static_assert(std::is_base_of<A, R>::value, "R must derive from A");
char r[sizeof(R)];
((R*)r)->foo = returns_some_valid_foo();
new (r) R;
return *((R*)r);
}
B b1; // Blows up (Could you somehow prevent this from compiling without changing B?)
B b2 = make_A<B>(); // Works fine?
Sheepishly assuming that C++ works like C somewhere under the hood, I'm guessing that this would be similar to having a struct instance in C, initializing it by hand, and then calling some method (in this case B's constructor) on the finished product.
Again, I'm not interested in whether you should do this or not, it's just a technical question.
EDIT:
If you wonder what this could be useful for, I could use it to pull out values into a plain struct from, say, a configuration file in a really terse manner. Yes it does use macros but call it a stub until C++ gets compile time reflection:
#define config_key($x, $def) $x = foo->get<decltype($x)>(#$x, ($def))
struct Record : A {
int config_key(a, 3); // Second parameter is default value
string config_key(b, "something");
}
auto record = make_A<Record>();
(Using A and foo here to stay consistent with what I wrote above, make_A is actually part of a class that does config)
This:
((R*)r)->foo = returns_some_valid_foo();
is undefined behavior. There is no object of type R at r. Full stop. If you flip the two lines so that you create the R first, then you're fine (modulo r being insufficiently aligned).
Or really, just:
R r;
r.foo = returns_some_valid_foo();
return r;

How to run Parameterized Tests with fixture member values in Google Test (gtest)?

What I want to achieve is a Paramaterized Test TEST_P(MyFixtureClass, DoStuff), with which I can test different values. Though said values shouldn't be constants, like those typically passed to INSTANTIATE_TEST_CASE_P. Moreover, I would want to use the values within some other fixture class - ideally.
There doesn't seem to be anything out there, which covers using fields instead of static values when creating parameterized tests. The official documentation doesn't seem to cover this either - sadly.
But to avoid introducing the XY-problem in this question, here is the equivalent pseudo code:
The parameterized fixture, MyFixture:
struct MyFixture : OtherFixture, ::testing::WithParamInterface<float>
{
float a;
void SetUp() override
{
a = GetParam();
}
};
OtherFixture would look like this:
struct OtherFixture : testing::Test
{
float a;
float b;
float c;
void SetUp() override
{
a = CalculateSomeFloat();
b = CalculateSomeFloat();
c = CalculateSomeFloat();
}
};
The test case would be something like:
// This here is the key aspect.
// Basically, I do not want to write a bunch of tests for a, b and c.
// Rather, I'd just test all 3 with this one.
TEST_P(MyFixture, DoStuff)
{
...bunch of tests
}
And lastly, we would instantiate the parameterized tests:
INSTANTIATE_TEST_CASE_P(MyFloatTesting, MyFixture, ::testing::Values(
OtherFixture::a, OtherFixture::b, OtherFixture::c
));
Obviously, OtherFixture::a is inappropriate, but it illustrates where I would want to refer to a field, within a inherited fixture class (or any fixture class for that matter).
So is there any way to achieve this with gtest? I do not necessarily need to use parameterized tests. Simply avoiding having to write the same tests, for different objects is fine by me.
Any suggestions are much appreciated!
I think you need to use ::testing::Combine.
And change the parameters from float to std::tuple<float, float OtherFixture::*>.
using OtherFixtureMemberAndValue = std::tuple<float, float OtherFixture::*>;
struct MyFixture : OtherFixture, ::testing::WithParamInterface<OtherFixtureMemberAndValue>
{
float a = std::get<0>(GetParam());
auto& memberToTest()
{
return this->*std::get<1>(GetParam());
}
};
To define set of parameters use this approach:
const auto membersToTest = testing::Values(
&OtherFixture::a,
&OtherFixture::b,
&OtherFixture::c
);
const auto floatValuesToTest = testing::Values(
2.1,
3.2
// ...
);
INSTANTIATE_TEST_CASE_P(AllMembers,
MyFixture,
testing::Combine(floatValuesToTest, membersToTest));
Then you can write your tests generic with respect to members of OtherFixture:
TEST_P(MyFixture, test)
{
ASSERT_EQ(a, memberToTest());
}
I would also advice that you wrote PrintTo for float OtherFixture::*:
void PrintTo(float OtherFixture::*member, std::ostream* os)
{
if (member == &OtherFixture::a)
*os << "&OtherFixture::a";
else if (member == &OtherFixture::b)
*os << "&OtherFixture::b";
else if (member == &OtherFixture::c)
*os << "&OtherFixture::c";
else
*os << "&OtherFixture::? = " << member;
}
In this way you get nice message in case of failure:
[ FAILED ] AllMembers/MyFixture.test/5, where GetParam() = (3.2,
&OtherFixture::c)
comparing to nasty, meaningless message w/o PrintTo:
[ FAILED ] AllMembers/MyFixture.test/5, where GetParam() = (3.2,
4-byte object <10-00 00-00>)

How to return different classes from one function?

I have a question, though it is not limited to C++. How to return totally different class from one function?
f() {
in case one: return A;
in case two: return B;
in case three: return C;
}
For example, I have two balls in the space, according to the position and the size, there are three situations for the two balls to intersect with each other, i.e, non-intersection, at point, a and circle. How can I return different class in one function?
Thanks.
If you can afford Boost then this sounds like a perfect application for Boost.Variant.
struct NoIntersection {
// empty
};
struct Point {
// whatever
};
struct Circle {
// whatever
};
typedef boost::variant<NoIntersection, Point, Circle> IntersectionResult;
IntersectionResult intersection_test() {
if(some_condition){
return NoIntersection();
}
if(other_condition){
return Point(x, y);
}
if(another_condition){
return Circle(c, r);
}
throw std::runtime_error("unexpected");
}
You then process your result with a static visitor:
struct process_result_visitor : public boost::static_visitor<> {
void operator()(NoIntersection) {
std::cout << "there was no intersection\n";
}
void operator()(Point const &pnt) {
std::cout << "there was a point intersection\n";
}
void operator()(Circle const &circle) {
std::cout << "there was a circle intersection\n";
}
};
IntersectionResult result = intersection_test();
boost::apply_visitor(process_result_visitor(), result);
EDIT: The visitor class must derive from boost::static_visitor
UPDATE: Prompted by some critical comments I've written a little benchmark program. Four approaches are compared:
boost::variant
union
class hierarchy
boost::any
These are the results in my home computer, when I compile in release mode with default optimizations (VC08):
test with boost::variant took 0.011 microseconds
test with union took 0.012 microseconds
test with hierarchy took 0.227 microseconds
test with boost::any took 0.188 microseconds
Using boost::variant is faster than a union and leads (IMO) to the most elegant code. I'd guess that the extremely poor performance of the class hierarchy approach is due to the need to use dynamic memory allocations and dynamic dispatch. boost::any is neither fast nor especially elegant so I wouldn't consider it for this task (it has other applications though)
The classes you want to return should be derived from a common base class. So, you can return the base type. For Example (this is not a code, just marking the pattern, you can use an interface if your language supports this abstraction or abstract class for example. If you use C++ you will have to return a pointer of the common class):
class A : public Common
{
..
}
class B : public Common
{
..
}
class C : public Common
{
..
}
Common f() {
in case one: return A;
in case two: return B;
in case three: return C;
}
In addition to #Manuel's Boost.Variant suggestion, take a look at Boost.Any: has similar purpose as Boost.Variant but different tradeoffs and functionality.
boost::any is unbounded (can hold any type) while boost::variant is bounded (supported types is encoded in variant type, so it can hold only values of these types).
// from Beyond the C++ Standard Library: An Introduction to Boost
// By Björn Karlsson
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include "boost/any.hpp"
class A {
public:
void some_function() { std::cout << "A::some_function()\n"; }
};
class B {
public:
void some_function() { std::cout << "B::some_function()\n"; }
};
class C {
public:
void some_function() { std::cout << "C::some_function()\n"; }
};
int main() {
std::cout << "Example of using any.\n\n";
std::vector<boost::any> store_anything;
store_anything.push_back(A());
store_anything.push_back(B());
store_anything.push_back(C());
// While we're at it, let's add a few other things as well
store_anything.push_back(std::string("This is fantastic! "));
store_anything.push_back(3);
store_anything.push_back(std::make_pair(true, 7.92));
void print_any(boost::any& a);
// Defined later; reports on the value in a
std::for_each(
store_anything.begin(),
store_anything.end(),
print_any);
}
void print_any(boost::any& a) {
if (A* pA=boost::any_cast<A>(&a)) {
pA->some_function();
}
else if (B* pB=boost::any_cast<B>(&a)) {
pB->some_function();
}
else if (C* pC=boost::any_cast<C>(&a)) {
pC->some_function();
}
}
In order to be able to do anything useful with the result, you have to return an object which has a common baseclass. In your case you might want to let A, B, and C inherit from a common "intersection-class"; a class which is common for all objects which represents some form of intersection. Your function f would then return an object of this type.
The classes you want to return should have a common parent class or interface.
If those classes do not have anything in common, that, I suppose, is untrue, you can return object.
This feature is also known as polymorphism.
In c++ base class pointer can point to derived class object. We can make use of this fact to code a function that meets your requirements:
class shape{};
class circle: public shape
{};
class square: public shape
{};
shape* function(int i){ // function returning a base class pointer.
switch(i) {
case 1: return new circle();
case 2: return new square();
}
}
There is one other option available. You can return a union of pointers to objects along with a tag that tells the caller which member of the union is valid. Something like:
struct result {
enum discriminant { A_member, B_member, C_member, Undefined } tag;
union result_data {
A *a_object;
B *b_object;
C *c_object;
} data;
result(): tag(Undefined) {}
explicit result(A *obj): tag(A_member) { data.a_object = obj; }
explicit result(B *obj): tag(B_member) { data.b_object = obj; }
explicit result(C *obj): tag(C_member) { data.c_object = obj; }
};
I would probably use Boost.variant as suggested by Manuel if you have the option.
You can't. You can only return a base pointer to different derived classes. If this is absolutely, 100% needed, you can use exceptions as a ugly hack, but that's obviously not recommended at all.
Even if you could return three different types of objects from the function, what would you do with the result? You need to do something like:
XXX ret_val = getIntersection();
If getIntersection returned three different types of objects, XXX would have to change based on what getIntersection was going to return. Clearly this is quite impossible.
To deal with this, you can define one type that defines enough to cover all the possibilities:
class Intersection {
enum { empty, point, circle, sphere};
point3D location;
size_t radius;
};
Now getIntersection() can return an Intersection that defines what kind of intersection you have (and BTW, you need to consider the fourth possibility: with two spheres of the same radius and same center point, the intersection will be a sphere) and the size and location of that intersection.
The limitation is based on the declared return type of your method. Your code states:
f() {
in case one: return A;
in case two: return B;
in case three: return C;
}
When in reality the compiler requires something like this:
FooType f() {
in case one: return A;
in case two: return B;
in case three: return C;
}
It must be possible to convert the A, B, and C to a FooType, typically through simple inheritance, though I won't get into the differences between subclasses vs subtyping.
There are approaches that can get around this. You could create a class or struct (C++) which has fields for each different type of possible return and use some flag field to indicate which field is the actual returned value.
class ReturnHolder {
public int fieldFlag;
public TypeA A;
public TypeB B;
public TypeC C;
}
The enum example in another answer is more of the same. The reason why that is a hack is that the code that handles the return from this method will have to have lots of code to handle each of the different possibilites, like so
main(){
FooType *x = new FooType();
ReturnHolder ret = x.f();
switch (ret.fieldFlag)
case: 1
//read ret.A
case: 2
//read ret.B
case: 3
//read ret.C
}
And that's without even going into trying to do it with Exceptions which introduce even bigger problems. Maybe I'll add that in later as an edit.
And by the way, as you said that question "is not limited to C++":
1) dynamic languages, of course, make it piece of cake:
# python
def func(i):
if i == 0:
return 0
elif i == 1:
return "zero"
else
return ()
2) some functional languages (Haskell, OCaml, Scala, F#) provide nice built-in variants that are called Algebraic Data Types (article has good samples).
In languages that reflection, it is easier to achieve. In cpp, if you have a standard set of classes to be returned (pointers), create an enumeration and return the enum value. Using this value you can infer the class type. This is a generic way in case there is no common parent class
You really shouldn't want to be doing that, and should really come up with a better design instead of forcing a square peg in a round hole. And with most languages you can't do it at all, by design. You will never really know what you are working with, and neither will the compiler ahead of time, ensuring extra bugs and weird behavior and incomprehensibility.