Defining functions using backslash in c++ - c++

I saw people using backslash when they define functions in Macros as:
#define ClassNameNoDebug(TypeNameString) \
static const char* typeName_() { return TypeNameString; } \
static const ::Foam::word typeName
I did a very easy test. But I got a bunch of errors. The testing code is as follows:
In my testmacro.h file:
#define declearlarger(first,second) \
double whichislarger(double first,double second){ return (first>second) ? fisrt : second;}
In my main() function:
int second =2;
int first =1;
cout << declearlarger(first,second) << endl;
The errors are:
/home/jerry/Desktop/backslash/backslash_test/testmacro.h:7: error: expected primary-expression before 'double'
double whichislarger(double first,double second){ return (first>second) ? fisrt : second;}
^
/home/jerry/Desktop/backslash/backslash_test/testmacro.h:7: error: expected ';' before 'double'
double whichislarger(double first,double second){ return (first>second) ? fisrt : second;}
^
/home/jerry/Desktop/backslash/backslash_test/main.cpp:24: error: expected primary-expression before '<<' token
cout << declearlarger(first,second) << endl;
^
That concludes all my testing errors. Can anyone give some suggestions why these errors pop up?

You're trying to use a function definition (generated by your macro) inside an expression. C++ does not allow such a thing. You could instead define your macro to be
#define declearlarger(first,second) \
(((first)>(second)) ? (first) : (second))
and then it would work. Also note that none of the errors come from the backslash, they are all generated because of the function definition/expression clash.

Related

Error facing with range function in DPC++

I'm new to Sycl/DPC++ language. I wrote a sample vector addition code using Unified shared memory (USM):
#include<CL/sycl.hpp>
#include<iostream>
#include<chrono>
using namespace sycl;
int main()
{
int n=100;
int i;
queue q{ };
range<1>(n);
int *a=malloc_shared<int>(n,q);
int *b=malloc_shared<int>(n,q);
int *c=malloc_shared<int>(n,q);
for(i=0;i<n;i++)
{
a[i]=i;
b[i]=n-i;
}
q.parallel_for(n,[=](auto &i){
c[i]=a[i]+b[i];
}).wait();
for(i=0;i<n;i++){
std::cout<<c[i]<<std::endl;
}
free(a,q);
free(b,q);
free(c,q);
return 0;
}
When I compile it I get the following error:
warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'n' [-Wvexing-parse]
range<1>(n);
^~~
vec_add.cpp:11:1: note: add enclosing parentheses to perform a function-style cast
range<1>(n);
^
( )
vec_add.cpp:11:9: note: remove parentheses to silence this warning
range<1>(n);
^ ~
vec_add.cpp:11:10: error: redefinition of 'n' with a different type: 'range<1>' vs 'int'
range<1>(n);
^
vec_add.cpp:8:5: note: previous definition is here
int n=100;
^
1 warning and 1 error generated.
How to fix this error?
error: redefinition of 'n' with a different type: 'range<1>' vs 'int'
Two variables with the same name within the same scope create confusion to the compiler, so it might be the reason for the error which you are getting. You can try defining the value of n globally say for eg: #define N 100 in this case, set
range<1>(n);
to
range<1> (N);
and use that in your code.
If you want to declare the size locally then assign another variable (r) to the range as
range<1> r (n);
Now you can directly pass the 'r' variable as a parameter to the parallel_for.

How to call AWS CPP SDK functions from C [duplicate]

This question already has answers here:
How to call C++ function from C?
(7 answers)
Closed 3 years ago.
I am currently using the AWS CPP SDK for s3 and I am trying to call functions in my C++ files from a C file.
I have already looked up guides on how to call C++ functions from a C file, and I have done so successfully with simple, non-AWS functions. However, when I try and use the same guide to do so with an AWS CPP SDK function it does not work correctly. Below are the files and the commands I am running.
list_buckets.cpp
#include <stdio.h>
#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/Bucket.h>
using namespace std;
extern "C" {
void listBuckets();
}
void listBuckets() {
Aws::S3::S3Client s3_client;
auto outcome = s3_client.ListBuckets();
if (outcome.IsSuccess()) {
cout << "Your Amazon S3 buckets:" << endl;
Aws::Vector<Aws::S3::Model::Bucket> bucket_list = outcome.GetResult().GetBuckets();
for (auto const &bucket : bucket_list) {
cout << " * " << bucket.GetName() << endl;
}
} else {
cout << "ListBuckets error: " << outcome.GetError().GetExceptionName() << " - " << outcome.GetError().GetMessage() << endl;
}
}
int main(int argc, char const *argv[]) {
Aws::SDKOptions options;
Aws::InitAPI(options);
cout << "Listing buckets from list_buckets.cpp" << endl;
listBuckets();
Aws::ShutdownAPI(options);
return 0;
}
list_buckets.h
#include <aws/core/Aws.h>
void listBuckets();
list_buckets.c
#include "list_buckets.h"
int main(int argc, char const *argv[]) {
Aws::SDKOptions options;
Aws::InitAPI(options);
printf("Listing buckets from list_buckets.c\n");
listBuckets();
Aws::ShutdownAPI(options);
return 0;
}
To run list_buckets.cpp, I use g++ -std=c++17 -Wall -laws-cpp-sdk-core -laws-cpp-sdk-s3 list_buckets.cpp -o list_buckets && ./list_buckets, and the output is:
Your Amazon S3 buckets:
* bucket-name1
* bucket-name2
* bucket-name3
To build the library files for listing the AWS buckets, I run g++ -std=c++17 -laws-cpp-sdk-core -laws-cpp-sdk-s3 list_buckets.cpp -shared -o liblist_buckets.so.
To run list_buckets.c, I run gcc -I/Library/Developer/CommandLineTools/usr/include/c++/v1 -L. -llist_buckets list_buckets.c. However, it only produces errors which I have provided below.
In file included from list_buckets.c:1:
In file included from ./list_buckets.h:1:
In file included from /usr/local/include/aws/core/Aws.h:17:
In file included from /usr/local/include/aws/core/utils/logging/LogLevel.h:20:
In file included from /usr/local/include/aws/core/utils/memory/stl/AWSString.h:20:
In file included from /usr/local/include/aws/core/utils/memory/stl/AWSAllocator.h:21:
In file included from /usr/local/include/aws/core/utils/memory/AWSMemory.h:20:
In file included from /usr/local/include/aws/core/utils/memory/MemorySystemInterface.h:20:
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:98:1: error: unknown type name '_LIBCPP_BEGIN_NAMESPACE_STD'
_LIBCPP_BEGIN_NAMESPACE_STD
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:100:7: error: expected ';' after top level declarator
using ::size_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:100:8: error: expected identifier or '('
using ::size_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:101:7: error: expected ';' after top level declarator
using ::div_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:101:8: error: expected identifier or '('
using ::div_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:102:7: error: expected ';' after top level declarator
using ::ldiv_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:102:8: error: expected identifier or '('
using ::ldiv_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:104:7: error: expected ';' after top level declarator
using ::lldiv_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:104:8: error: expected identifier or '('
using ::lldiv_t;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:106:7: error: expected ';' after top level declarator
using ::atof;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:106:8: error: expected identifier or '('
using ::atof;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:107:7: error: expected ';' after top level declarator
using ::atoi;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:107:8: error: expected identifier or '('
using ::atoi;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:108:7: error: expected ';' after top level declarator
using ::atol;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:108:8: error: expected identifier or '('
using ::atol;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:110:7: error: expected ';' after top level declarator
using ::atoll;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:110:8: error: expected identifier or '('
using ::atoll;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:112:7: error: expected ';' after top level declarator
using ::strtod;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:112:8: error: expected identifier or '('
using ::strtod;
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make: *** [executeListBucketsLib] Error 1
I am stuck on how to resolve this issue. Any and all help/guidance is greatly appreciated.
Change list_buckets.h
#include <aws/core/Aws.h>
extern "C" {
void listBuckets();
}
This tells the C compiler what the linking syntax is. This affects the function naming scheme that the linker uses to resolve symbols.

Preprocessor ## pasting operator

What I am trying to achieve is creation of these three classes as mentioned in the code but just trying to use pre-processer in handy so that these similar classes can be created and executed rather than writing individual codes for them:
#include <iostream>
#define MYMACRO(len,baselen)
using namespace std;
class myclass ## len
{
int MYVALUE ## baselen;
public:
myclass ## len ## ()
{
cout << endl;
cout << " For class" ## len ## "'s function 'myFunction" ## len ## "' the value is: " << MYVALUE ## baselen << endl;
}
};
int main()
{
MYMACRO(10,100)
//myclass10 ob1;
MYMACRO(20,200)
//myclass20 ob2;
MYMACRO(30,300)
//myclass30 ob3;
myclass10 ob1;
myclass20 ob2;
myclass30 ob3;
cout << endl;
return 0;
}
Now I don't know whether the it can be done & since I am getting this error. If yes then please someone solve the error and enlighten me if no then please give the reason for the same so I am also reassured that we are on same page! The error is:
[root#localhost C++PractiseCode]# g++ -o structAndPreprocessor structAndPreprocessor.cpp
structAndPreprocessor.cpp:5: error: invalid token
structAndPreprocessor.cpp:6: error: invalid function declaration
structAndPreprocessor.cpp:7: error: invalid token
structAndPreprocessor.cpp:9: error: invalid token
structAndPreprocessor.cpp:9: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp:12: error: invalid token
structAndPreprocessor.cpp: In function `int main()':
structAndPreprocessor.cpp:25: error: `myclass10' was not declared in this scope
structAndPreprocessor.cpp:25: error: expected `;' before "ob1"
structAndPreprocessor.cpp:26: error: `myclass20' was not declared in this scope
structAndPreprocessor.cpp:26: error: expected `;' before "ob2"
structAndPreprocessor.cpp:27: error: `myclass30' was not declared in this scope
structAndPreprocessor.cpp:27: error: expected `;' before "ob3"
[root#localhost C++PractiseCode]#
You need to use \ at each end of your line to define your macro (and likely remove the using statement from the macro)
using namespace std;
#define MYMACRO(len,baselen) \
class myclass ## len \
{ \
int MYVALUE ## baselen; \
(...snip...) \
}\
};
Note the absence of escape on last line
Most likely you're doing Cpp and using Macros is discouraged. You'd better use either templates or traditional dynamic code (dpeending on your needs). Compared to macros, template bring the additional type checking at compilation and provide much more readable error messages.
The macro solution you present is a solution I've used before, but I would look at approaching this differently. The macro solution is a unwieldy and difficult to maintain and debug for all but the most trivial code.
Have you thought about generating the code you need from a template? Using Cheetah or Mako to fill out a source template would be quite a bit cleaner, and you could drive the generation from a configuration file, so you don't have to hand-maintain your list of classes.
You'd have a myclass.tmpl template file that looks something like this :
#for len, baselen in enumerate(mylist_of_classes_i_want_to_generate)
class MyClass$len
{
int MYVALUE$baselen;
public:
MyClass$len()
{
cout << endl;
cout << " For class $len's function 'myFunction $len' the value is: " << MYVALUE$baselen << endl;
}
};
#end for
You'd then call cheetah to autogenerate the code at the start of your build flow prior to compilation.

define macro with template as variable

i'm trying to use a macro to create some static variables.
my problem is, how do i do define a macro with 2 parameters, the first is a template and the second a static variable. the template should have more than 1 type.
for example:
#define macro(x, y, z, v) x::y z = v;
int main(int argc, char *argv[]) {
// this works
macro(std::queue<int>, value_type, test, 4)
// this also works
std::pair<int, int>::first_type x = 3;
// this is produsing some compiler errors
macro(std::pair<int, int>, first_type, test2, 4)
return 0;
}
and is it even possible to do this?
here is the error:
main.cpp(47) : warning C4002: too many actual parameters for macro 'macro'
main.cpp(47) : error C2589: 'int' : illegal token on right side of '::'
main.cpp(47) : error C2589: 'int' : illegal token on right side of '::'
main.cpp(47) : error C2143: syntax error : missing ',' before '::'
main.cpp(50) : error C2143: syntax error : missing ';' before '}'
main.cpp(51) : error C2143: syntax error : missing ';' before '}'
inspired by Joachim Pileborg
#define macro(x, y, z, v, ...) x<__VA_ARGS__>::y z = v;
...
// now it works
macro(std::pair, first_type, test2, 4, int, int)
thx Joachim
It's not really a solution but merely a work-around:
#define COMMA ,
macro(std::pair<int COMMA int>, first_type, test2, 4)
or a little bit more readable:
#define wrap(...) __VA_ARGS__
macro(wrap(std::pair<int, int>), first_type, test2, 4)
It's because the preprocessor that handles macros is quite stupid. It sees five arguments in the second macro "call", the first one being std::pair<int and the second one int>. You can't have macro arguments that contains comma.
You might want to look into variadic macros, and re-arrange so that the class is last in the macro.
There are a couple of ways to get rid of that top-level comma.
typedef std::pair<int, int> int_pair;
macro(int_pair, first_type, test2, 4)
macro((std::pair<int, int>), first_type, test2, 4);
#define macro2(x1, x2, y, z, v) x1, x2::y z = v;
macro2(std::pair<int, int> first_type, test2, 4)
Incidentally, I'd leave off the ; from the macro, and use it wherever the macro is used. That makes the code look more natural.

Strange behaviour with templates and #defines

I have the following definitions:
template<typename T1, typename T2>
class Test2
{
public:
static int hello() { return 0; }
};
template<typename T>
class Test1
{
public:
static int hello() { return 0; }
};
#define VERIFY_R(call) { if (call == 0) printf("yea");}
With these, I try to compile the following:
VERIFY_R( Test1<int>::hello() );
this compiles fine
VERIFY_R( (Test2<int,int>::hello()) );
this also compiles fine, notice the parentheses around the call.
VERIFY_R( Test2<int,int>::hello() );
This, without the parentheses produces a warning and several syntax errors:
warning C4002: too many actual parameters for macro 'VERIFY_R'
error C2143: syntax error : missing ',' before ')'
error C2059: syntax error : ')'
error C2143: syntax error : missing ';' before '}'
error C2143: syntax error : missing ';' before '}'
error C2143: syntax error : missing ';' before '}'
fatal error C1004: unexpected end-of-file found
What's going on here?
This happens with VS2008 SP1.
The comma inside a macro can be ambiguous: an extra set of parentheses (your second example) is one way of disambiguating. Consider a macro
#define VERIFY(A, B) { if ( (A) && (B) ) printf("hi"); }
then you could write VERIFY( foo<bar, x> y ).
Another way of disambiguating is with
typedef Test1<int,int> TestII;
VERIFY_R( TestII::hello() );
The preprocessor is a dumb text replacement tool that knows nothing about C++. It interprets
VERIFY_R( Test1<int,int>::hello() );
as
VERIFY_R( (Test1<int), (int>::hello()) );
which calls VERIFY_R with too many parameters. As you noted, additional parentheses fix this:
VERIFY_R( (Test1<int,int>::hello()) );
The question remains, however, why you need the preprocessor anyway. The macro you used in your question could just as well be an inline function. If you real code doesn't do anything requiring the preprocessor, try to get rid of macros. They just cause pain.
The comma in <int, int> is treated as an argument separator for the macro, rather than for the template. The compiler therefore thinks you're calling VERIFY_R with two arguments (Test1<int and int>::hello()), when it requires only one. You need to use variadic macros to expand everything supplied to the macro:
#define VERIFY_R(...) { if ((__VA_ARGS__) == 0) printf("yea");}
It is generally a good idea to wrap macro arguments in parentheses, as well, to prevent other kinds of weird substitution errors.
The preprocessor doesn't know that < and > are supposed to be brackets, so it interprets the expression as two macro arguments, Test1<int and int>::hello(), separated by the ,. As you say, it can be fixed by surrounding the entire expression with parentheses, which the preprocessor does recognise as brackets.
I'm not sure if this is an error in your reporting here or the actual problem, but your last VERIFY_R is still referencing Test1, rather than Test2.