how to deal with method name duplication in legacy code - c++

i have in my legacy code this
#define max(x, y) (x > y ? x : y)
#define min(x, y) (x < y ? x : y)
that bean used allot in the application , now i try to compile it in freeBSD
and i keep getting :
/usr/include/c++/4.2/bits/istream.tcc:123:35: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:124:45: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:143:33: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:144:43: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:438:48: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:441:53: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:449:47: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:489:48: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:493:53: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:501:47: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:507:53: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:806:43: error: macro "max" requires 2 arguments, but only 1 given
i guess its the name of the methods in the code ( the macros ) .
now changing the name its to much work.
how can i keep using it but avoiding the compiler to mixup ?

What was the reason to define those macros in the first place? It's C++, no need for any macros, especially not those that are already given as functions to you by the standard (It always bothers me when including <windows.h> and getting complaints about their stupid min and max macros).
That being said, a quick and dirty solution might be to substitute your macro definitions with
#include <algorithm>
using std::min;
using std::max;
Though, this still pollutes the global namespace those are now proper function names that can be hidden by any local variables or any other functions or methods and are not just replaced everywhere by a stupid text-substituting preprocessor.
Other than that consider including any system include files before those macros (or usings).

Related

error: expected unqualified-id before numeric constant: std::array and std::vector size allocation

The error stems from macro definition in my code:
#define NUM_ROWS 3
The following is the pastebin link to complete source code:
Complete Source Code
The compilation error is
code.cpp:14:18: error: expected unqualified-id before numeric constant
#define NUM_ROWS 3
^
code.cpp:19:29: note: in expansion of macro ‘NUM_ROWS’
vector<array<int,NUM_COLS>>(NUM_ROWS) matrix;
^~~~~~~~
code.cpp:14:18: error: expected ‘)’ before numeric constant
#define NUM_ROWS 3
^
The following is the pastebin link to the compiler log:
Compiler log
I have looked up related errors on Stack Overflow but the contexts seem different in the case of those errors. In this case, I intend to use the macros to pre-define the size of the std::array and std::vector objects. I thought of using macros since my understanding is that I should use constants for the sizes.
Appreciate your thoughts
Some pointers that might help you:
vector<array<int,NUM_COLS>>(NUM_ROWS) matrix;
is wrong, the proper way to construct a std::vector having NUM_ROWS elements is
vector<array<int,NUM_COLS>> matrix(NUM_ROWS);
Secondly, I watched your code (you might want to add it to the question for posterity)
void set_matrix(vector<array<int,NUM_COLS>>(NUM_ROWS)&)
and similarly defined functions, will not work NUM_ROWS is not part of the type of vector, try
void set_matrix(vector<array<int,NUM_COLS>>&)

Why can't I use assert with std::is_same?

Can somebody explain to me why on Earth does this code snippet refuse to work?
#include <cassert>
#include <type_traits>
using namespace std;
int main()
{
assert(is_same<int, int>::value);
}
Compilation fails because, according to the compiler:
prog.cpp:7:33: error: macro "assert" passed 2 arguments, but takes just 1
assert(is_same<int, int>::value);
^
prog.cpp: In function 'int main()':
prog.cpp:7:2: error: 'assert' was not declared in this scope
assert(is_same<int, int>::value);
^
What? is_same<int, int>::value is undoubtedly one argument. Also assert is declared at this scope, and the compiler itself confirmed it in the previous error!
http://ideone.com/LcMVkn
The macro splits your parameter(s) like this:
is_same<int , int>::value
// ^^ par1 ^^// ^^ par2 ^^
As assert() is a macro definition (with one parameter), it's handled by the C-preprocessor. The preprocessor is unaware of c++ syntax like template parameters gouped in angle brackets (<>) separated with ,. So the parameter expression is split up like shown above.
You can avoid that using extra parenthesis, so the C-preprocessor will take that parameter as a whole:
assert((is_same<int, int>::value));
// ^ ^

Is it possible to define a macro from a macro

Here is what I am thinking.
#define prefix_1 1
#define prefix_2 2
#define prefix_3 3
And I want to define a macro using the prefixes above — like macro macro_prefix_1 macro_prefix_2 — and I expect them to turn into macro_1 macro_2, etc. Just like the code below
#define macro_##prefix_1 I_am_macro_1
#define macro_##prefix_2 I_am_macro_2
Is this possible?
Unfortunately, what you are trying to do is impossible. The (##) directive is impossible to use within a macro declaration. It is only possible to use it within the definition as such.
#define glue(a,b) a ## b
glue(c,out) << "test";
Example borrowed from cplusplus.com
Below, I have written an example of what you want to do.
#include <stdio.h>
#define prefix_1 1
#define prefix_2 2
#define prefix_3 3
#define macro_##prefix_1 "macro_1"
#define macro_##prefix_2 "macro_2"
#define macro_##prefix_3 "macro_3"
int main(){
printf("%s\n%s\n%s\n", macro_prefix_1, macro_prefix_2, macro_prefix_3);
return 0;
}
When you try to compile the above code you will get this build log.
||=== Build: Debug in file_test (compiler: GNU GCC Compiler) ===|
main.cpp|7|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|7|error: '##' cannot appear at either end of a macro expansion|
main.cpp|8|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|8|error: '##' cannot appear at either end of a macro expansion|
main.cpp|9|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|9|error: '##' cannot appear at either end of a macro expansion|
main.cpp||In function 'int main()':|
main.cpp|13|error: 'macro_prefix_1' was not declared in this scope|
main.cpp|13|error: 'macro_prefix_2' was not declared in this scope|
main.cpp|13|error: 'macro_prefix_3' was not declared in this scope|
||=== Build failed: 6 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
So if you want to be able to have macro's you will just have to add the prefix normally. Luckily you were basically already doing this, but adding "##". Hope this helped.

Compiler errors with Poco::Logger on Linux - function declaration treated as macro

I've been trying to build executable that uses Poco::Application class as its basis, but compiler is giving following errors pointing to Poco code.
In file included from /home/mie/Poco/poco-1.4.6p4/Util/include/Poco/Util/Application.h:48:0,
from /home/mie/myproject/src/main.cpp:15:
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:152:59: error: macro "log" passed 3 arguments, but takes just 1
In file included from /home/mie/Poco/poco-1.4.6p4/Util/include/Poco/Util/Application.h:48:0,
from /home/mie/myproject/src/main.cpp:15:
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:427:58: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:428:86: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:601:72: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:610:100: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:621:30: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:627:42: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:633:33: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:639:45: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:645:30: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:651:42: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:657:32: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:663:44: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:669:31: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:675:43: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:681:36: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:687:48: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:693:30: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:699:42: error: macro "log" passed 4 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:705:30: error: macro "log" passed 2 arguments, but takes just 1
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:711:42: error: macro "log" passed 4 arguments, but takes just 1
In file included from /home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:44:0,
from /home/mie/Poco/poco-1.4.6p4/Util/include/Poco/Util/Application.h:48,
from /home/mie/myproject/src/main.cpp:15:
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Channel.h:75:15: error: expected unqualified-id before ‘__extension__’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Channel.h:75:15: error: expected ‘)’ before ‘__extension__’
In file included from /home/mie/Poco/poco-1.4.6p4/Util/include/Poco/Util/Application.h:48:0,
from /home/mie/myproject/src/main.cpp:15:
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:145:7: error: expected unqualified-id before ‘__extension__’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:145:7: error: expected ‘)’ before ‘__extension__’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:149:7: error: expected unqualified-id before ‘__extension__’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:149:7: error: expected ‘)’ before ‘__extension__’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:152:7: error: variable or field ‘log’ declared void
In file included from /home/mie/Poco/poco-1.4.6p4/Util/include/Poco/Util/Application.h:48:0,
from /home/mie/myproject/src/main.cpp:15:
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:427:7: error: variable or field ‘log’ declared void
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:428:7: error: variable or field ‘log’ declared void
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:601:21: error: variable or field ‘log’ declared void
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:601:21: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:603:2: error: expected primary-expression before ‘if’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:603:2: error: expected ‘}’ before ‘if’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:610:13: error: ‘Logger’ has not been declared
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:610:21: error: variable or field ‘log’ declared void
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:610:21: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x [enabled by default]
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:612:2: error: expected primary-expression before ‘if’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:612:2: error: expected ‘}’ before ‘if’
/home/mie/Poco/poco-1.4.6p4/Foundation/include/Poco/Logger.h:616:1: error: expected declaration before ‘}’ token
make[2]: *** [CMakeFiles/app.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/app.dir/all] Error 2
Here I'm including latest version of Poco (1.4.6p4) from my home directory, but I've tried 1.4.2p1-2.el6 from CentOS 6.5 repositories with same result. On OS X I didn't have this problem (I believe the library version there was 1.4.2).
If I look what's in Poco/Logger.h on line 152, where the first error points to, it seems to be a function declaration rather than macro as the error states.
//
// Logger.h
//
// $Id: //poco/1.4/Foundation/include/Poco/Logger.h#5 $
//
// Library: Foundation
// Package: Logging
// Module: Logger
//
// Definition of the Logger class.
... (comment continues)
#ifndef Foundation_Logger_INCLUDED
#define Foundation_Logger_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/Channel.h"
#include "Poco/Message.h"
#include "Poco/Format.h"
#include <map>
#include <vector>
#include <cstddef>
namespace Poco {
class Exception;
class Foundation_API Logger: public Channel
/// Logger is a special Channel that acts as the main
/// entry point into the logging framework.
... (comment continues)
{
public:
... (other declarations)
void log(const Exception& exc, const char* file, int line); <= line 152
/// Logs the given exception with priority PRIO_ERROR.
///
/// File must be a static string, such as the value of
/// the __FILE__ macro. The string is not copied
/// internally for performance reasons.
... (and so on)
So why is my compiler treating this function declaration as a reference to macro?
As a side note, there was a weird error earlier in the build process that I just commented out. Maybe these are related. I tried to use fmod function from tgmath.h in an inline function and compiler gave this error six times for one line of code:
/.../header.h:418: error: ”void*” is not a pointer-to-object type
/.../header.h:418: error: ”void*” is not a pointer-to-object type
/.../header.h:418: error: ”void*” is not a pointer-to-object type
/.../header.h:418: error: ”void*” is not a pointer-to-object type
/.../header.h:418: error: ”void*” is not a pointer-to-object type
/.../header.h:418: error: ”void*” is not a pointer-to-object type
And this is the code in a header file that triggered the error:
inline void ProgressCounter::createTimeString(
std::string& timeString,
const long long& elapsedTotalS)
{
short elapsedH = (short)elapsedTotalS / 3600;
//short elapsedS = 0;
short elapsedS = fmod(elapsedTotalS, 60); <= error here
short elapsedM = 0;
//short elapsedM = fmod(elapsedTotalS - elapsedS, 3600) / 60;
char timeCString[10];
snprintf(timeCString, 10, "%02u:%02u:%02u", elapsedH, elapsedM, elapsedS);
timeString = timeCString;
}
The header tgmath.h is included and the code compiled without problems on OS X. I don't understand where the void* in the error refers to.
I've been using GCC 4.4.7 on CentOS 6.5 and GCC 4.4.6.3-1ubuntu5 on Ubuntu 12.04.
<math.h> and <tgmath.h> define a lot of macros, including a log macro which conflicts with anything with the same name.
In C++ code, you should rather include <cmath> or <ctgmath> where the type-generic macros are replaced by C++ function overloads.
PS: at least for gcc, <ctgmath> seems to require C++11 support, so you'll have to add "-std=c++0x" or "-std=c++11" to the compilation options.
Try including your POCO libraries first and see if that helps. I had a problem just a few days ago in VS 2010 on Windows in which a lot of Windows APIs suddenly became undefined when I had #included the POCO libraries last. Moving them ahead of other #includes fixed the problem.
Having fixed it, I did not do deep analysis of exactly what item had caused the problem.

C++ Macro improperly terminated macro invocation

In C++ is there a mechanism to allow non terminated macros to be expressed?
This is a contrived example:
#define MACRO(x, y) x + y
#define MACROC1(x) MACRO(x,
#define MACROC2(y) y)
//...expecting 3
int foo = MACROC1(1) MACROC2(2);
I receive the error improperly terminated macro invocation from MSVC.
When I run cl -E file.cpp I see that the code below has been generated:
int c = 1 + 1 + 2);
In visual studio compilation fails with errors:
error C2059: syntax error : ')'
IntelliSense: improperly terminated macro invocation
I don't think this is possible. The C precompiler expands macros depth-first, so the MACROC1 will be full expanded before the MACROC2 is even considered. Then, it will find the MACRO with and incomplete argument list and throws an error.
Generally speaking, you should avoid defining macros that build other macro calls. Compilers tend not to agree in what those mean.
Your code would translate to :
int foo = MACRO(1, 2;
Which is wrong - it is an incomplete (improperly terminated) invocation of macro MACRO.