C++ preprocessor and overloading issues - c++

I have the following problem:
Let's consider we have
#define SET callMe
#define COLUMN(x) #x
and in our main block of our program we have the following line:
SET(COLUMN(price)="hi"); which after the preprocessor running is translated to:
#callMe("price"="hi");
I need function callMe signature to be callMe(string str) so that leaves us to have to make something to make the "price"="hi" to "price=hi" and let callMe function to handle the rest of the problem. Last thing to state is that all this program I describe is a part of a Table class.
The only option I have is overload the operator = so the "price"="hi" translated to the wanted one, but I can't get what I should overload because I first thought that doing the following overload
#std::string operator=(std::string str) as a member function of the Table class but it seems I can't get it right on track.
Any clues of how I can achieve the wanted operations?

Is this any good to you?
#define SECOND_PASS(x) callMe(#x)
#define COLUMN(x) x
#define SET(x) SECOND_PASS(x)
which results in:
callMe("price=\"hi\"");
This essentially gets the preprocessor to remove COLUMN before converting to a string.

To get what you want, you would have to write your code as SET(COLUMN(price)"=hi").
You can't overload operator=() for a built-in type. This is done for sanity maintenance, among other reasons.
C++ overloading is not intended to allow you to force the compiler to parse a different language.
P.S. Overloading operator=() in the Table class only handles the case where a Table is on the left-hand side of the =. That would require COLUMN(x) to return a Table object, probably not what you want. You could use an adaptor class to get this effect, but the syntax of COLUMN(x) doesn't include which table this column is from, so you're stuck there too.
One way out there solution would look something like this:
class ColumnSetter
{public:
ColumnSetter(const char* name): name(name), value(0) {}
ColumnSetter& operator=(const char* value_) { value = value_; }
operator std::string const &() const { std::string result(name);
if(value) { result.append('='); result.append(value); } return result; }
private:
const char* name;
const char* value;
};
#define COLUMN(x) ColumnSetter(#x)
void callMe(const std::string& param);
Reformat and de-inline to whatever coding standards you have.

You mean like
#define SET(x) (CallMe(x))
ps - usual disclaimer about using the preprocessor

This should be done with classes that overload the various logical operators to create an abstract syntax tree instead of actually performing the operation. Then you can express various SQL expressions as C++ code and get an abstract syntax tree out which can then be serialized into an SQL WHERE clause.
This isn't very hard, and if you are careful about it, it will be pretty efficient. It's much better than trying to use preprocessor hackery to create an SQL expression builder.

Related

Met c++ code " #define ELEMENT(TYPE, FIELD)"

#define ELEMENT(TYPE, FIELD)\
bool get##FIELD(TYPE *field) const throw()\
{ \
return x_->get##FIELD(y_, field);\
} \
I never met code like this before.
First, why do we put code in #define, is it a macro? So, I can use ELEMENT() later in other places?
Second, what is ##? What I can find online is "The ## operator takes two separate tokens and pastes them together to form a single token. The resulting token could be a variable name, class name or any other identifier."
Could someone tell me how I should know what this kind of code works?
Yes, ELEMENT() is a preprocessor macro, which is just a fancy way to replace one piece of text with another piece of text before the compiler is invoked. At the site where a macro is invoked, it is replaced with the text content of the macro. If the macro has parameters, each parameter is replaced with the text that the caller passed in to the macro.
In this case, the TYPE parameter is being used as-is within the macro text, whereas the FIELD parameter is being concatenated with get via ## concatenation to produce a new token identifier get<FIELD>.
ELEMENT() can be used like this, for example:
class MyClass
{
ELEMENT(int, IntValue) // TYPE=int, FIELD=IntValue
ELEMENT(string, StrData) // TYPE=string, FIELD=StrData
// and so on ...
};
Which will be expanded by the preprocessor to this code, which is what the compiler actually sees:
class MyClass
{
bool getIntValue(int *field) const throw()
{
return x_->getIntValue(y_, field);
}
bool getStrData(string *field) const throw()
{
return x_->getStrData(y_, field);
}
// and so on ...
};
I'm sorry to tell you, someone tried to be clever.
#define is used to textually replace one piece of text with another. The 2 arguments can be passed as a kind of arguments. Normally, such an argument is a token. However, thanks to ##, one can do token concatenation.
Let's take an example: ELEMENT(int, Cost);
This will result in the following code being injected:
bool getCost(int *field) const throw()
...
So as you can see, int is kept as token, while Cost is glued together into getCost.
I hope you found this in legacy code, cause using the preprocessor is considered bad coding in C++. The language hasn't been able to get rid of most usages. However they are providing alternatives to most common usages.
The #include and header guards have gotten replacements with the C++20 modules proposal.

Why doesn't C++ allow const after ::?

Folks,
Problem Statement - Does C++ allow a (static) const be limited to a class scope, so I can get rid of #defines that pollute entire namespace?
My observation is NO (in the following DIFFERENT examples), and I'd like to find out why and what's the best alternative. VS generates error C2589: 'const' : illegal token on right side of '::'
EXAMPLE1
// a.h
class A
{
…
..
static const uint_32 myConst = 1234;
};
//b.cpp
include “a.h”
…
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
EXAMPLE 2
// a.h
class A
{
…
..
enum blah
{
...
myConst = 1234,
..
};
};
//b.cpp
include “a.h”
...
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
When you take your macro:
#define CONST 1234
and substitute it for where you use it:
static const int CONST = 1234;
The end result is nonsense:
static const int 1234 = 1234;
In another instance:
Int a1[a::CONST];
This also becomes nonsense:
Int a1[a::1234];
This all begs the question, what are you trying to do?
It looks like you're trying to create a member variable with the same name as your macro, CONST, here:
class A
{
static const int CONST = 1234;
};
However since when this code is compiled the macro has already been defined, the preprocessor changes this by substituting the macro before the compiler itself can get a crack at it. By the time the code is compiled, it looks like this:
class A
{
static const int 1234 = 1234;
};
Best is to just do away with the macro entirely, and then retrofit your code to use proper constants like you're trying to do here. Don't mix and match. At the very least, don't use the same name for the member as you do for the macro.
First of all your class is called A, as in capital A, not a. The class name is used to qualify the constant you are trying to use. So, change your code to use A::CONST. By the way, this is C++ not C# or Java, so there is no such thing as an Int, unless for some bizarre reason you decided to invent your own integer type.
As an aside, using all caps to name constants can collide with macros and is a good way to get into trouble, especially since pre-processing happens first and macros are substituted for all cases of the constants. This can often lead to invalid C++ code with syntax errors that are difficult to understand. That's why you should never use all caps to name constants, since this is a convention most commonly used for macros.
If I may make a guess, it looks like you're trying to use :: the same way you use . in Python.
It looks like you really don't understand what the scope resolution operator does, or how it works.
:: has a very specific, and quite limited usage. Until you understand it better, we're going to have a really hard time helping you.

C++ stream second insertion operator

Is it possible to define a second insertion operator to have two modes of outputting a class? Say e.g. one that outputs all members and one that just outputs some basic unique identifier that is grep-able in a log? If so, is there an operator that is usually chosen? I would guess as analogy to << one might use <<< if that is legal?
Thanks
If you want to output only the id, then the best idea is probably to provide a method to get the id in a type that's streamable (e.g. std::string id() const;). That's much more intuitive to other people working on the code than some strange operator use.
Your suggestion of <<< (it's not possible to create new operators in C++, but ignoring that for a moment) reveals that you're happy for there to be different code at the point of call. Therefore, the only benefit you'd get would be the saving of a few character's source code; it isn't worth the obfuscation.
By way of contrast, there are situations where you want the same streaming notation to invoke different behaviours, such as switching between id-only and full data, or different representations such as tag/value, CSV, XML, and binary. These alternatives are usually best communicated by either:
using different stream types (e.g. XMLStream rather than std::ostream), and defining XMLStream& operator<<(XMLStream&, const My_Type&) etc, and/or
using stream manipulators - you can create your own - random Google result: http://www.informit.com/articles/article.aspx?p=171014&seqNum=2
There's no such thing already defined or in use by convention.
Also, you cannot define your own operators in C++, you have to use one of the ones already in the language and overloadable, and <<< isn't an operator in C++, so it is out anyway.
I'd strongly recommend you don't use some other operator for this. (See rule #1 here for a more thorough explanation.) If you have subtle differences between output operations, well-chosen functions names go a long way for making better code than unclear operators arbitrarily picked.
No. You can't define your own operators (<<< doesn't exist in C++). But you can define a id() method returning a string and output this.
There is no such operator as <<< in C++.
You are, however, free to implement, for example operator <(ostream&,Object&), which would do what you want. The problem is, code may get unreadable when you try to chain < and << together.
you can use operator | for instance. Another way of doing this is to define small tag classes for which the operator is overloaded; example (pretty simplistic but you get the point):
template< class T >
struct GrepTag
{
GrepTag( const T& );
T value;
}
template< class T >
Greptag< T > MakeGrepTag( const T& x )
{
return GrepTag< T >( x );
}
template< class T >
MyClass& MyClass::operator << ( const GrepTag< T >& g )
{
//output g.value here
}
MyClass() << MakeGrepTag( "text" );
Yet another way, more like the standard streams, is to use a tag as well but keep some state internally:
struct GrepTag
{
}
MyClass& MyClass::operator << ( const GrepTag& g )
{
grepState = true;
}
template< class T >
MyClass& MyClass::operator << ( const T& )
{
if( grepState )
{
//output special
grepState = false;
}
else
{
//output normal
}
}
MyClass() << GrepTag() << "text";
You cannot define your own operators in C++. You can only overload those that exist.
So I recomend not using an operator for outputting basic unique identifier grep-able in a log. This doesn't correspond to any existing operator role. Use a method instead, such as exportToLog().

Is there a better alternative to preprocessor redirection for runtime tracking of an external API?

I have sort of a tricky problem I'm attempting to solve. First of all, an overview:
I have an external API not under my control, which is used by a massive amount of legacy code.
There are several classes of bugs in the legacy code that could potentially be detected at run-time, if only the external API was written to track its own usage, but it is not.
I need to find a solution that would allow me to redirect calls to the external API into a tracking framework that would track api usage and log errors.
Ideally, I would like the log to reflect the file and line number of the API call that triggered the error, if possible.
Here is an example of a class of errors that I would like to track. The API we use has two functions. I'll call them GetAmount, and SetAmount. They look something like this:
// Get an indexed amount
long GetAmount(short Idx);
// Set an indexed amount
void SetAmount(short Idx, long amount);
These are regular C functions. One bug I am trying to detect at runtime is when GetAmount is called with an Idx that hasn't already been set with SetAmount.
Now, all of the API calls are contained within a namespace (call it api_ns), however they weren't always in the past. So, of course the legacy code just threw a "using namespace api_ns;" in their stdafx.h file and called it good.
My first attempt was to use the preprocessor to redirect API calls to my own tracking framework. It looked something like this:
// in FormTrackingFramework.h
class FormTrackingFramework
{
private:
static FormTrackingFramework* current;
public:
static FormTrackingFramework* GetCurrent();
long GetAmount(short Idx, const std::string& file, size_t line)
{
// track usage, log errors as needed
api_ns::GetAmount(Idx);
}
};
#define GetAmount(Idx) (FormTrackingFramework::GetCurrent()->GetAmount(Idx, __FILE__, __LINE__))
Then, in stdafx.h:
// in stdafx.h
#include "theAPI.h"
#include "FormTrackingFramework.h"
#include "LegacyPCHIncludes.h"
Now, this works fine for GetAmount and SetAmount, but there's a problem. The API also has a SetString(short Idx, const char* str). At some point, our legacy code added an overload: SetString(short Idx, const std::string& str) for convenience. The problem is, the preprocessor doesn't know or care whether you are calling SetString or defining a SetString overload. It just sees "SetString" and replaces it with the macro definition. Which of course doesn't compile when defining a new SetString overload.
I could potentially reorder the #includes in stdafx.h to include FormTrackingFramework.h after LegacyPCHIncludes.h, however that would mean that none of the code in the LegacyPCHIncludes.h include tree would be tracked.
So I guess I have two questions at this point:
1: how do I solve the API overload problem?
2: Is there some other method of doing what I want to do that works better?
Note: I am using Visual Studio 2008 w/SP1.
Well, for the cases you need overloads, you could use a class instance that overloads operater() for a number of parameters.
#define GetAmount GetAmountFunctor(FormTrackingFramework::GetCurrent(), __FILE__, __LINE__)
then, make a GetAmountFunctor:
class GetAmountFunctor
{
public:
GetAmountFunctor(....) // capture relevant debug info for logging
{}
void operator() (short idx, std::string str)
{
// logging here
api_ns::GetAmount(idx, str);
}
void operator() (short idx)
{
/// logging here
api_ns::GetAmount(Idx);
}
};
This is very much pseudocode but I think you get the idea. Whereever in your legacy code the particular function name is mentioned, it is replaced by a functor object, and the function is actually called on the functor. Do consider you only need to do this for functions where overloads are a problem. To reduce the amount of glue code, you can create a single struct for the parameters __FILE__, __LINE__, and pass it into the constructor as one argument.
The problem is, the preprocessor doesn't know or care whether you are calling SetString or defining a SetString overload.
Clearly, the reason the preprocessor is being used is that it it oblivious to the namespace.
A good approach is to bite the bullet and retarget the entire large application to use a different namespace api_wrapped_ns instead of api_ns.
Inside api_wrapped_ns, inline functions can be provided which wrap counterparts with like signatures in api_ns.
There can even be a compile time switch like this:
namespace api_wrapped_ns {
#ifdef CONFIG_API_NS_WRAPPER
inline long GetAmount(short Idx, const std::string& file, size_t line)
{
// of course, do more than just wrapping here
return api_ns::GetAmount(Idx, file, line);
}
// other inlines
#else
// Wrapping turned off: just bring in api_ns into api_wrapper_ns
using namespace api_ns;
#endif
}
Also, the wrapping can be brought in piecemeal:
namespace api_wrapped_ns {
// This function is wrapped;
inline long GetAmount(short Idx, const std::string& file, size_t line)
{
// of course, do more than just wrapping here
return
}
// The api_ns::FooBar symbol is unwrapped (for now)
using api_ns::FooBar;
}

Is it possible to treat macro's arguments as regular expressions?

Suppose I have a C++ macro CATCH to replace the catch statement and that macro receive as parameter a variable-declaration regular expression, like <type_name> [*] <var_name> or something like that. Is there a way to recognize those "fields" and use them in the macro definition?
For instance:
#define CATCH(var_declaration) <var_type> <var_name> = (<var_type>) exception_object;
Would work just like:
#define CATCH(var_type, var_name) var_type var_name = (var_type) exception_object;
As questioned, I'm using g++.
You can't do it with just macros, but you can be clever with some helper code.
template<typename ExceptionObjectType>
struct ExceptionObjectWrapper {
ExceptionObjectType& m_unwrapped;
ExceptionObjectWrapper(ExceptionObjectType& unwrapped)
: m_unwrapped(unwrapped) {}
template<typename CastType>
operator CastType() { return (CastType)m_wrapped; }
};
template<typename T>
ExceptionObjectWrapper<T> make_execption_obj_wrapper(T& eobj) {
return ExceptionObjectWrapper<T>(eobj);
}
#define CATCH(var_decl) var_decl = make_exception_obj_wrapper(exception_object);
With these definitions,
CATCH(Foo ex);
should work. I will admit to laziness in not testing this (in my defence, I don't have your exception object test with). If exception_object can only be one type, you can get rid of the ExceptionObjectType template parameter. Further more, if you can define the cast operators on the exception_object itself you can remove the wrappers altogether. I'm guessing exception_object is actually a void* or something though and your casting pointers.
What compiler are you using? I've never seen this done in the gcc preprocessor, but I can't say for sure that no preprocessor out there can implement this functionality.
What you could do however is run your script through something like sed to do your prepreprocessing so to speak before the preprocessor kicks in.
Hmmm... I'm just guessing, but why don't you try something like this : :)
#define CATCH(varType,varName) catch(varType& varName) { /* some code here */ }