implement field access with functions - c++

I want to replace object field access with functions to make it easy for a program analyzer I am building. Is there a simple way to do this? I came up with the following hack with my own set and get functions:
struct Foo
{
int f1;
int f2;
};
// convert v = t->f1 to v = (int)get(t, "f1")
void * get (struct Foo * t, char * name)
{
if (!strcmp(name, "f1")) return t->f1;
else if (!strcmp(name, "f2")) return t->f2;
else assert(0);
}
// convert t->f1 = v; to set(t, "f1", v)
void set (struct Foo * t, char * name, void * v)
{
if (!strcmp(name, "f1")) t->f1 = (int)v;
else if (!strcmp(name, "f2")) t->f2 = (int)v;
else assert(0);
}
Edit: C or C++ hacks would work.

So, as far as I understand you are looking for some reflection library for c/c++?
In this case, there is quite a big difference between c and c++.
For C++, you can use boost describe.
For C there are several libraries, bottom line all solution come down to defining your structs with macros, something like:
MY_STRUCT(s,
MY_MEMBER(int, y),
MY_MEMBER(float, z))
You can see a few examples here.

Related

how to write a function that links other functions in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Lets say I have functions A, B, & C.
I would like to write a function which looks like:
Linker(A,B,C,{{0,1,0},{0,0,1},{0,0,0}});
where the arrays correspond to which element in the first list will be called. In other words, when A finishes, it starts the second element B, when B finishes it calls the third element C, when C finishes nothing is called.
Linker would then unroll into
generic preprocessing
run A
generic postprocessing
generic preprocessing
run B
generic postprocessing
generic preprocessing
run C
generic postprocessing
The idea being that this would make it easier to link functions together, and would save me some time in writing the pre and postprocessing steps. Also organization, error-proofing, understandability, etc... Is this Idea possible in C? would I need to use C++? how do I begin implementing an idea like this?
I am using stm32ide as my compiler as this code will run on an embedded device.
You could do this by setting up some "processing" class that stores pointers to your functions and the links you want to establish between them:
class processor {
private:
std::vector<void (*)()> funcs;
std::vector<std::pair<int, int>> links;
public:
void add_func(void (*func)()) { funcs.push_back(func); }
void link(int from, int to) { links.push_back({from, to}); }
void call(int indx) {
// Make the call
funcs.at(indx)();
// Call any links
for(auto it : links) {
if(it.first == indx) { call(it.second); }
}
}
};
Then to use it, you just need to add your functions and links, and then call call():
int main() {
processor p;
p.add_func(A);
p.add_func(B);
p.add_func(C);
p.link(0, 1); // A -> B
p.link(1, 2); // B -> C
p.call(0); // Call A
return 0;
}
See it in action here: https://ideone.com/M1Qj6f
If I understand you correctly you want to pass a function as a parameter to another function.
For c++ you can use function pointers.
#include <iostream>
void helloWorld()
{
std::cout << "Hello World" << std::endl;
}
int main()
{
helloWorld();
# Here we get the memory adress of the function helloWorld.
auto secondHelloWorld = &helloWorld;
# Here, an implicit converstion is going on.
auto thridHelloWorld = helloWorld;
secondHelloWorld();
thirdHelloWorld();
std::cin.get();
}
If you want to be more explicit with the types, you can write
#include <iostream>
void helloWorld()
{
std::cout << "Hello World" << std::endl;
}
int main()
{
helloWorld();
void(*secondHelloWorld)() = helloWorld;
void(*thridHelloWorld)() = helloWorld;
secondHelloWorld();
thirdHelloWorld();
std::cin.get();
}
I can not help you with how you should precisly implement this. I would need to know you requirements.
HTH
Your question should be clarified. If I understand well, you want to wrap a function, as done in a context manager. You should precise what is the signature of your functions A, B, C and how must be used {{0,1,0},{0,0,1},{0,0,0}}.
So to keep it simple, I'll assume that these three functions takes no parameter and do not return anything.
#include <stdio.h>
void context_manager(
void (*f)(),
void (*enter)(),
void (*exit)()
) {
enter();
f();
exit();
}
void my_enter() { printf("generic preprocessing\n"); }
void my_exit() { printf("generic postprocessing\n\n"); }
void a() { printf("run A\n"); }
void b() { printf("run B\n"); }
void c() { printf("run C\n"); }
void linker(void **fs, unsigned n) {
for (unsigned i = 0; i < n; i++) {
context_manager(fs[i], my_enter, my_exit);
}
}
int main() {
void * fs[] = {a, b, c};
linker(fs, sizeof(fs) / sizeof(void *));
return 0;
}
Result:
generic preprocessing
run A
generic postprocessing
generic preprocessing
run B
generic postprocessing
generic preprocessing
run C
generic postprocessing
You can obviously adapt the signature of f and linker to pass some parameter(s).
The hard part is that: Linker(A,B,C,{{0,1,0},{0,0,1},{0,0,0}}); cannot be written in C. The language lacks:
automatic processing or variable numbers of parameters for a function: you have to give a hint for the number and the function will have to guess the type
litteral multi-dimensional arrays do not exist in the language.
Said differently, I can imagine how to write something able to accept that syntax (apart from the semicolon) in Python, but not in C. Building a thing able to process a bunch of functions and chain them according to something is not a problem and can be done in C. But I cannot guess what the something should be, and how you intend to pass the functions and the something to the thing while respecting C syntax.
Assuming I understand what you're going for, and assuming all the functions have the same return type and argument lists, you could set up an array of function pointers and an array of integers to indicate which function to execute out of that list:
void A(void) { puts( "In A" ); }
void B(void) { puts( "In B" ); }
void C(void) { puts( "In C" ); }
/**
* Call each of the functions in f based on the values in seq;
* each seq[i] is treated as an index into f.
*
* A negative value in seq[i] indicates the end of the sequence.
*
* Inputs:
* f - list of functions we want to execute
* seq - specifies the order in which the functions are to be executed
*/
void Linker( void (*f[])(void), int *seq )
{
for ( int i = 0; seq[i] >= 0; i++ )
{
f[seq[i]]();
}
}
int main( void )
{
/**
* Use compound literals to set up each array.
*/
Linker( (void (*[])(void)) {A, B, C}, (int []) {0, 1, 2, 2, 1, 2, 0, 0, 0, -1} );
}
Output:
In A
In B
In C
In C
In B
In C
In A
In A
In A
If the functions have different return types, or if they have the same return types but take different parameter lists (or even the same parameter lists with different values), then this will need to be fleshed out a bit. You may need to create a C equivalent of a "functor" (basically a struct type that abstracts away the function return type and other details). But it should give you some ideas.

how to use boost context v2

boost::context library was updated to version v2 and the changes broke all my previous code relying on boost::jump_fcontext()
Also the old boost::jump_fcontext() is no longer available in the new API. The new boost::context v2 changed so much that I can't understand it. The boost provided examples don't help me.
Here is pseudo code of the program structure I'm trying to archive with the new execute_context:
struct myctx
{
int var;
boost::context::execution_context fctx;
myctx()
: var(0), fctx("how to ctor")
{}
static void ctx_func(ctx_data * ptr) {
while(ptr->var++ < 1000) {
ptr->fctx("how to jump into main() myctx ??")
}
}
};
int main()
{
myctx mctx;
while(1)
mctx.fctx("how to jump into ctx_func() ??");
return 0;
}
How do I replace those strings with real C++?? I don't understand what are the possible arguments to boost::context::execution_context
My usage of the boost::context was that I saved the current context into myctx and switched into multiple other myctx's in unordered fasion. With boost::jump_fcontext this was fairly clearly done.
why dont't you initialize 'fctx'? Even it will not compile because of ctx_data() - ctor (not same name as myctx) ...
maybe you meant something like:
struct myctx
{
int var;
execution_context< myctx * > fctx;
myctx()
: var(0), fctx( myctx::ctx_func)
{}
static execution_context< myctx * > ctx_func(execution_context< myctx * > mctx, ctx_data * ptr) {
while(ptr->var++ < 1000) {
// jump into main()
std::tie(mctx, ptr) = mctx( ptr);
}
return std::move( mctx);
}
};
I've no idea for what you want to pass myctx pointer

Is there a way to disallow pointer comparison in C++?

I have a (working) code base where I want to add something like an is_equivalent member to a class hierarchy. Scattered throughout the code base there are comparisons like
if (foo == bar) ...
where foo and bar are ordinary pointers to objects in the class hierarchy. I would like to introduce usage like the following (as a virtual function in the base class):
if (foo->is_equivalent(bar)) ...
so that the notion of "equality" is relaxed. A concrete geometric example might be a shape hierarchy, where a Circle should be considered equivalent to an Ellipse with equal major and minor axes (not a perfect analogy).
What I would like to do is have the compiler help me find all the instances where I have done direct pointer comparison. One thought I had was to provide something like an operator==(const Shape *, const Shape *) but that isn't even allowed by C++.
Some pointer comparisons might need to stay pointer comparison, but some will need to be changed into a virtual method call. I'll need to look at each one. What approaches are there to identify all these kinds of comparisons? Temporarily breaking either the build or execution is fine. There is pretty good test coverage.
I have read the question C++ Trick to avoid pointer comparison which is similar, but more limited because the accepted answer assumes the existence of a factory class.
You could write a custom code analysis tool. Here's a minimal (and rather trivial) example I've built using libclang. This filters out every binary operator in the source. By the means of refining this, you could gather all pointer equality comparisons from the AST.
#include <clang-c/Index.h>
#include <stdio.h>
static void printBinOp(CXCursor cursor)
{
CXSourceRange range = clang_getCursorExtent(cursor);
CXSourceLocation begin = clang_getRangeStart(range);
CXSourceLocation end = clang_getRangeEnd(range);
CXFile file;
unsigned begin_offset, end_offset, length;
// retrieve physical location of AST node
clang_getSpellingLocation(begin, &file, NULL, NULL, &begin_offset);
clang_getSpellingLocation(end, NULL, NULL, NULL, &end_offset);
length = end_offset - begin_offset;
// Open the file, error checking omitted for clarity
CXString xfname = clang_getFileName(file);
const char *fname = clang_getCString(xfname);
FILE *fhndl = fopen(fname, "r");
clang_disposeString(xfname);
// Read the source
char buf[length + 1];
fseek(fhndl, begin_offset, SEEK_SET);
fread(buf, length, 1, fhndl);
buf[length] = 0;
fclose(fhndl);
// and print it
printf("Comparison: %s\n", buf);
}
static enum CXChildVisitResult ptrCompVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
if (clang_getCursorKind(cursor) == CXCursor_BinaryOperator) {
printBinOp(cursor);
}
return CXChildVisit_Recurse;
}
int main()
{
CXIndex index = clang_createIndex(0, 0);
CXTranslationUnit tu = clang_parseTranslationUnit(index, "foo.cpp", NULL, 0, NULL, 0, CXTranslationUnit_None);
clang_visitChildren(clang_getTranslationUnitCursor(tu), ptrCompVisitor, NULL);
clang_disposeTranslationUnit(tu);
clang_disposeIndex(index);
return 0;
}
The example file I've used was this imaginary C++ source file (named foo.cpp):
class Foo {
int foo;
};
class Bar {
int bar;
}
int main()
{
void *f = new Foo();
void *b = new Bar();
bool alwaystrue_1 = f == f;
bool alwaystrue_2 = b == b;
return f == b;
}
For which my tool printed this:
Comparison: f == f
Comparison: b == b
Comparison: f == b

Convenient C++ struct initialisation [duplicate]

This question already has answers here:
C++ Structure Initialization [duplicate]
(17 answers)
Closed 3 months ago.
I'm trying to find a convenient way to initialise 'pod' C++ structs. Now, consider the following struct:
struct FooBar {
int foo;
float bar;
};
// just to make all examples work in C and C++:
typedef struct FooBar FooBar;
If I want to conveniently initialise this in C (!), I could simply write:
/* A */ FooBar fb = { .foo = 12, .bar = 3.4 }; // illegal C++, legal C
Note that I want to explicitly avoid the following notation, because it strikes me as being made to break my neck if I change anything in the struct in the future:
/* B */ FooBar fb = { 12, 3.4 }; // legal C++, legal C, bad style?
To achieve the same (or at least similar) in C++ as in the /* A */ example, I would have to implement an annoying constructor:
FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) {}
// ->
/* C */ FooBar fb(12, 3.4);
Which feels redundant and unnecessary. Also, it is pretty much as bad as the /* B */ example, as it does not explicitly state which value goes to which member.
So, my question is basically how I can achieve something similar to /* A */ or better in C++?
Alternatively, I would be okay with an explanation why I should not want to do this (i.e. why my mental paradigm is bad).
EDIT
By convenient, I mean also maintainable and non-redundant.
Since style A is not allowed in C++ and you don't want style B then how about using style BX:
FooBar fb = { /*.foo=*/ 12, /*.bar=*/ 3.4 }; // :)
At least help at some extent.
Designated initializes will be supported in c++2a, but you don't have to wait, because they are officialy supported by GCC, Clang and MSVC.
#include <iostream>
#include <filesystem>
struct hello_world {
const char* hello;
const char* world;
};
int main ()
{
hello_world hw = {
.hello = "hello, ",
.world = "world!"
};
std::cout << hw.hello << hw.world << std::endl;
return 0;
}
GCC Demo
MSVC Demo
Update 2021
As #Code Doggo noted, anyone who is using Visual Studio 2019 will need to set /std:c++latest  for the "C++ Language Standard" field contained under Configuration Properties -> C/C++ -> Language.
You could use a lambda:
const FooBar fb = [&] {
FooBar fb;
fb.foo = 12;
fb.bar = 3.4;
return fb;
}();
More information on this idiom can be found on Herb Sutter's blog.
Extract the contants into functions that describe them (basic refactoring):
FooBar fb = { foo(), bar() };
I know that style is very close to the one you didn't want to use, but it enables easier replacement of the constant values and also explain them (thus not needing to edit comments), if they ever change that is.
Another thing you could do (since you are lazy) is to make the constructor inline, so you don't have to type as much (removing "Foobar::" and time spent switching between h and cpp file):
struct FooBar {
FooBar(int f, float b) : foo(f), bar(b) {}
int foo;
float bar;
};
Your question is somewhat difficult because even the function:
static FooBar MakeFooBar(int foo, float bar);
may be called as:
FooBar fb = MakeFooBar(3.4, 5);
because of the promotion and conversions rules for built-in numeric types. (C has never been really strongly typed)
In C++, what you want is achievable, though with the help of templates and static assertions:
template <typename Integer, typename Real>
FooBar MakeFooBar(Integer foo, Real bar) {
static_assert(std::is_same<Integer, int>::value, "foo should be of type int");
static_assert(std::is_same<Real, float>::value, "bar should be of type float");
return { foo, bar };
}
In C, you may name the parameters, but you'll never get further.
On the other hand, if all you want is named parameters, then you write a lot of cumbersome code:
struct FooBarMaker {
FooBarMaker(int f): _f(f) {}
FooBar Bar(float b) const { return FooBar(_f, b); }
int _f;
};
static FooBarMaker Foo(int f) { return FooBarMaker(f); }
// Usage
FooBar fb = Foo(5).Bar(3.4);
And you can pepper in type promotion protection if you like.
Many compilers' C++ frontends (including GCC and clang) understand C initializer syntax. If you can, simply use that method.
Yet another way in C++ is
struct Point
{
private:
int x;
int y;
public:
Point& setX(int xIn) { x = Xin; return *this;}
Point& setY(int yIn) { y = Yin; return *this;}
}
Point pt;
pt.setX(20).setY(20);
Option D:
FooBar FooBarMake(int foo, float bar)
Legal C, legal C++. Easily optimizable for PODs. Of course there are no named arguments, but this is like all C++. If you want named arguments, Objective C should be better choice.
Option E:
FooBar fb;
memset(&fb, 0, sizeof(FooBar));
fb.foo = 4;
fb.bar = 15.5f;
Legal C, legal C++. Named arguments.
I know this question is old, but there is a way to solve this until C++20 finally brings this feature from C to C++. What you can do to solve this is use preprocessor macros with static_asserts to check your initialization is valid. (I know macros are generally bad, but here I don't see another way.) See example code below:
#define INVALID_STRUCT_ERROR "Instantiation of struct failed: Type, order or number of attributes is wrong."
#define CREATE_STRUCT_1(type, identifier, m_1, p_1) \
{ p_1 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
#define CREATE_STRUCT_2(type, identifier, m_1, p_1, m_2, p_2) \
{ p_1, p_2 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
#define CREATE_STRUCT_4(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3, m_4, p_4) \
{ p_1, p_2, p_3, p_4 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_4) >= (offsetof(type, m_3) + sizeof(identifier.m_3)), INVALID_STRUCT_ERROR);\
// Create more macros for structs with more attributes...
Then when you have a struct with const attributes, you can do this:
struct MyStruct
{
const int attr1;
const float attr2;
const double attr3;
};
const MyStruct test = CREATE_STRUCT_3(MyStruct, test, attr1, 1, attr2, 2.f, attr3, 3.);
It's a bit inconvenient, because you need macros for every possible number of attributes and you need to repeat the type and name of your instance in the macro call. Also you cannot use the macro in a return statement, because the asserts come after the initialization.
But it does solve your problem: When you change the struct, the call will fail at compile-time.
If you use C++17, you can even make these macros more strict by forcing the same types, e.g.:
#define CREATE_STRUCT_3(type, identifier, m_1, p_1, m_2, p_2, m_3, p_3) \
{ p_1, p_2, p_3 };\
static_assert(offsetof(type, m_1) == 0, INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_2) >= sizeof(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(offsetof(type, m_3) >= (offsetof(type, m_2) + sizeof(identifier.m_2)), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_1) == typeid(identifier.m_1), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_2) == typeid(identifier.m_2), INVALID_STRUCT_ERROR);\
static_assert(typeid(p_3) == typeid(identifier.m_3), INVALID_STRUCT_ERROR);\
The way /* B */ is fine in C++ also the C++0x is going to extend the syntax so it is useful for C++ containers too. I do not understand why you call it bad style?
If you want to indicate parameters with names then you can use boost parameter library, but it may confuse someone unfamiliar with it.
Reordering struct members is like reordering function parameters, such refactoring may cause problems if you don't do it very carefully.
What about this syntax?
typedef struct
{
int a;
short b;
}
ABCD;
ABCD abc = { abc.a = 5, abc.b = 7 };
Just tested on a Microsoft Visual C++ 2015 and on g++ 6.0.2. Working OK.
You can make a specific macro also if you want to avoid duplicating variable name.
For me the laziest way to allow inline inizialization is use this macro.
#define METHOD_MEMBER(TYPE, NAME, CLASS) \
CLASS &set_ ## NAME(const TYPE &_val) { NAME = _val; return *this; } \
TYPE NAME;
struct foo {
METHOD_MEMBER(string, attr1, foo)
METHOD_MEMBER(int, attr2, foo)
METHOD_MEMBER(double, attr3, foo)
};
// inline usage
foo test = foo().set_attr1("hi").set_attr2(22).set_attr3(3.14);
That macro create attribute and self reference method.
For versions of C++ prior to C++20 (which introduces the named initialization, making your option A valid in C++), consider the following:
int main()
{
struct TFoo { int val; };
struct TBar { float val; };
struct FooBar {
TFoo foo;
TBar bar;
};
FooBar mystruct = { TFoo{12}, TBar{3.4} };
std::cout << "foo = " << mystruct.foo.val << " bar = " << mystruct.bar.val << std::endl;
}
Note that if you try to initialize the struct with FooBar mystruct = { TFoo{12}, TFoo{3.4} }; you will get a compilation error.
The downside is that you have to create one additional struct for each variable inside your main struct, and also you have to use the inner value with mystruct.foo.val. But on the other hand, it`s clean, simple, pure and standard.
I personally have found that using constructor with struct is the most pragmatic way to ensure struct members are initialized in code to sensible values.
As you say above, small downside is that one does not immediatelly see what param is which member, but most IDEs help here, if one hovers over the code.
What I consider more likely is that new member is added and in this case i want all constructions of the struct to fail to compile, so developer is forced to review. In our fairly large code base, this has proven itself, because it guides developer in what needs attention and therefore creates self-maintained code.

Function which returns an unknown type

class Test
{
public:
SOMETHING DoIt(int a)
{
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: return INT;
case 2: return FLOAT;
case 3: return CHAR;
}
}
};
int main(int argc, char* argv[])
{
Test obj;
cout<<obj.DoIt(1);
return 0;
}
Now, using the knowledge that a = 1 implies that I need to return an integer, etc., is there anyway Doit() can return a variable of variable data type?
Essentially, with what do I replace SOMETHING ?
PS: I'm trying to find a an alternative to returning a structure/union containing these data types.
You can use boost::any or boost::variant to do what you want. I recommend boost::variant because you know the collection of types you want to return.
This is a very simple example, though you can do much more with variant. Check the reference for more examples :)
#include "boost/variant.hpp"
#include <iostream>
typedef boost::variant<char, int, double> myvariant;
myvariant fun(int value)
{
if(value == 0)
{
return 1001;
}
else if(value == 1)
{
return 3.2;
}
return 'V';
}
int main()
{
myvariant v = fun(0);
std::cout << v << std::endl;
v = fun(1);
std::cout << v << std::endl;
v = fun(54151);
std::cout << v << std::endl;
}
The output:
1001
3.2
V
I would use boost::variant instead of a union because you can't use non-POD types inside union. Also, boost::any is great if you don't know the type you are dealing with. Otherwise, I would use boost::variant because it is much more efficient and safer.
Answering the edited question: If you don't want to ship Boost with your code, take a look at bcp. The description of bcp from the same link:
The bcp utility is a tool for
extracting subsets of Boost, it's
useful for Boost authors who want to
distribute their library separately
from Boost, and for Boost users who
want to distribute a subset of Boost
with their application.
bcp can also report on which parts of
Boost your code is dependent on, and
what licences are used by those
dependencies.
C++ is a strongly-typed language, and has no concept of an unknown type. You could try using boost::any, which can (sort of) specify any type. I would question the design of your function, however.
If you know type at compile time you could use templates. If type depends on run-time, then using templates is not an option.
class Test
{
template<int> struct Int2Type {};
template<> struct Int2Type<1> { typedef int value_type; };
template<> struct Int2Type<2> { typedef float value_type; };
template<> struct Int2Type<3> { typedef char value_type; };
public:
template<int x> typename Int2Type<x>::value_type DoIt() {}; // error if unknown type used
template<> typename Int2Type<1>::value_type DoIt<1>() { return 2; };
template<> typename Int2Type<2>::value_type DoIt<2>() { return 1.2f; };
template<> typename Int2Type<3>::value_type DoIt<3>() { return 'a'; };
};
int main()
{
Test obj;
cout << obj.DoIt<2>();
return 0;
}
Use boost::any:
boost::any DoIt(int a)
{
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: return boost::any(INT);
case 2: return boost::any( FLOAT);
case 3: return boost::any( CHAR);
}
}
The usual way to achieve something like this is C, which doesn't always work in C++, is with a union and a type field:
enum SomeType { INT, FLOAT, CHAR };
struct Something
{
SomeType type;
union
{
int i;
float f;
char c;
};
};
Something DoIt(int a)
{
Something s;
switch (a)
{
case 1:
s.type = INT;
s.i = 2;
break;
case 2:
s.type = FLOAT;
s.f = 1.2;
break;
case 3:
s.type = CHAR;
s.c = 'a';
break;
default:
// ???
}
return s;
}
This doesn't work in C++ when one of the possible value types is a class with a non-trivial constructor, because it wouldn't always be clear which constructor should be called. Boost.Variant uses a more complex version of this approach to provide this kind of construct for any value types in C++.
You could use a struct containing a void* pointing to the value you want returned along with a size_t that indicates the size of the object being returned. Something like this:
struct Something {
void *value;
size_t size;
};
Remember that the void* should point to a value residing on the heap (i.e. dynamically allocated using new or malloc) and the caller should take care of freeing the allocated object.
Having said that, I think it's a bad idea overall.
Edit: You may also want to consider including a flag indicating what was returned in the above structure so that the caller can make sense of it, unless the caller knows what type to expect.
EDIT: boost::any using bcp (thanks AraK) seems to be the best solution to date but is it possible to prove (to some extent) that there exists no ANSI C++ solution to this problem?
You seem a bit confused about the terminology here.
First, let's call it ISO C++, shall we? It was standardized by ISO in 1998, and since then, that is what people have referred to when talking about "standard C++".
Now, what do you mean by an "ANSI C++ solution"?
A solution that compiles cleanly using only ANSI (or ISO) C++? If so, Boost is the ANSI C++ solution
A solution already implemented in the ANSI C++ standard library? If so then no, no such solution exists (and there is no "proof", other than "go read through the language standard and see if you can find such a class. If you can't, it isn't there".
A solution you could implement yourself using only ANSI C++. Then the answer is "yes, you could go copy the source code from Boost".
I can't imagine what kind of "proof" you'd be looking for. C++ is a document in prose form. It is not a mathematical equation. It can not be "proven", except by saying "go read the standard". Proving that something is defined in the language or in the standard library is easy -- simply point out where in the standard it is described. But proving that something isn't there is basically impossible -- except by enumerating every single sentence of the standard, and document that none of them describe what you're looking for. And I doubt you'll find anyone willing to do that for you.
Anyway, the correct standard C++ solution is to use Boost.
It is not a heavy-weight solution. Boost is pretty lightweight in that you can include exactly the bits you need, with no dependencies on the rest of the library collection.
From what you've described (a light application for a broad user base), there is zero reason not to use Boost. It can simplify your code and reduce the number of bugs caused by attempting to reinvent the wheel. When distributing the compiled executable, it has zero cost. The Boost.Any library is, like much of Boost, header-only, and is simply compiled into your executable. No separate libraries have to be distributed.
There is nothing to be gained by trying to reinvent the wheel. Your executable will be no smaller or more efficient, but it will be more buggy.
And I'm willing to bet that your home-brewed solution will not be ANSI C++. It will rely on some form of undefined behavior. If you want an ANSI-C++ solution, your best bet is Boost.
You could use a union:
typedef union {
int i;
float f;
char c;
} retType;
retType DoIt(int a){
retType ret;
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: ret.i = INT; break;
case 2: ret.f = FLOAT; break;
case 3: ret.c = CHAR; break;
}
return ret;
}
The Adobe Source Libraries also has adobe::any_regular_t, which allows you to store any type as long as it models the Regular concept. You would wrap your return value much the same way you would with boost::any. (There is also documentation on the linked page as to how adobe::any_regular_t differs from boost::any -- of course the type you pick should depend on the requirements of your code.)
You could pass by reference instead and be typesave and check if it worked at the same time, would not involve any additional library either (your kind of ansi C++ solution):
bool DoIt (int i, int & r1)
{
if (i==1) {r1 = 5; return true}
return false;
}
bool DoIt (int i, double & r2)
{
if (i==2) {r2 = 1.2; return true}
return false;
}
...
I find this solution often more clean in terms of design. It's unfortunate that funciton signatures don't allow multiple types as return types, but this way you can pass anything.
As of C++17 there is std::any and std::variant, which means you do not need third party library for this. From #Arak's answer the code will be modified a bit as below.
#include <variant>
#include <any>
#include <iostream>
typedef std::variant<char, int, double> myvariant;
myvariant fun(int value)
{
if(value == 0)
{
return 1001;
}
else if(value == 1)
{
return 3.2;
}
return 'V';
}
int main()
{
myvariant v = fun(0);
std::cout << v << std::endl;
v = fun(1);
std::cout << v << std::endl;
v = fun(54151);
std::cout << v << std::endl;
}
If the user knows what is put in, you could use a template to fix this. If not, I can't think of any solution.
I think the problem is about this function design. Have you tried overloading?
class Test
{
public:
int DoIt(int a) {
int INT = 2;
return INT;
}
float DoIt(float a) {
float FLOAT = 1.2;
return FLOAT;
}
char DoIt(char a) {
char CHAR = 'a';
return CHAR;
}
};
int main(int argc, char* argv[])
{
Test obj;
//....
switch(a)
case 1:
cout<< obj.DoIt(1);
break;
case 2:
cout<< obj.DoIt(1.01);
break;
case 3:
cout<< obj.DoIt("1");
break;
return 0;
}
Inside DoIt functions you can place more code and make them call other functions for not repeating code.
SOMETHING = void*
You have to cast the returned value, so you have to know what is returned.
void* DoIt(int a)
{
float FLOAT = 1.2;
int INT = 2;
char CHAR = 'a';
switch(a)
{
case 1: return &INT;
case 2: return &FLOAT;
case 3: return &CHAR;
}
}