简体   繁体   中英

Questions about C++ Preprocessor

I am learning C++ macro. And now I am totally confused. So help me! Below is my code, what I am trying to do is to use the C++ macro and call different functions using "template" such that I could only write one function and this function can be used to do the same things for different types. But when I compile this code, it throws the following errors.

testCPP.cpp: In function 'void test_int_Macro(int)':
testCPP.cpp:14: error: a function-definition is not allowed here before '{' token
testCPP.cpp:26: error: expected `}' at end of input**

#include<iostream>
#include<cstdint>

using namespace std;

#define Query_Data(Type)\
void test_##Type##_Macro(Type data){   \
    cout<<"Test: "<<sizeof(data)<<" "<<endl; \
    //cout<<"Type is "<<##Type##<<endl;\
}

Query_Data(int)
Query_Data(char)

int main(){
    cout<<sizeof(unsigned)<<endl;
    cout<<sizeof(char)<<endl;
    cout<<sizeof(int32_t)<<endl;
    int num=6;
    char c='a';
    Query_Data(num);
    //Query_Data(c);
}  

In C++, macros are very simple and stupid. The proeprocessor simply regurgitates whatever the macro is defined to be wherever you invoke it.

If you do the preprocessing on a piece of paper, what you come up with is:

int main(){
    cout<<sizeof(unsigned)<<endl;
    cout<<sizeof(char)<<endl;
    cout<<sizeof(int32_t)<<endl;
    int num=6;
    char c='a';
    void test_num_Macro(Type data){   
      cout<<"Test: "<<sizeof(data)<<" "<<endl; 
      //cout<<"Type is "<<##Type##<<endl;
    }
}  

The compiler gave you an error message which in this case was spot-on:

testCPP.cpp:14: error: a function-definition is not allowed here before '{' token

Look at the main function you end up with as a result of the preprocessing. It has a function declared within it. That, obviously, isn't allowed.

Now, if we follow this train of thought to the next logical stage, the question becomes "so how do I achieve what I'm trying to achineve?"

You said that:

what I am trying to do is to use the C++ macro and call different functions using "template" such that I could only write one function and this function can be used to do the same things for different types.

And there is a facility in C++ for exactly this. Coincidentally, they are called templates. Here's how you might use one here:

template <typename Val>
void test ()
{
  cout << "Test: " << sizeof (Val) << " " << endl;
}

int main(){
    cout<<sizeof(unsigned)<<endl;
    cout<<sizeof(char)<<endl;
    cout<<sizeof(int32_t)<<endl;
    int num=6;
    char c='a';
    test <char> ();
    test <int> ();
}

Macros are a cludge. The are not sophisticated, they skirt around the C++ type system, they are very hard to debug and maintain. It is generally advised to avoid using them unless you have no other choice. There are places when you do have no other choice -- but this isn't one of them.

John Dibling is quite right. But I would like to point out that the easiest way to debug preprocessor issues is usually by running g++ -E src.cpp which shows you the file after it's been preprocessed. (remove your #include's first or you'll get way too much output)

And the reason for the the "expects '}' at end of input" error is that commented line in your macro. The preprocessor treats it as an empty line (without a trailing ) and so doesn't look farther and leaves your '}' out of the define.

You should avoid using the preprocessor in C++ for anything but #include and include guards in header files.

Macros are simple text replacement snippets, so you will end up defining those functions inside main function, a thing you cannot do in C++. You can see it very well if you run your code through the preprocessor:

void test_int_Macro(int data){ cout<<"Test: "<<sizeof(data)<<" "<<endl;
void test_char_Macro(char data){ cout<<"Test: "<<sizeof(data)<<" "<<endl;

int main(){
    cout<<sizeof(unsigned)<<endl;
    cout<<sizeof(char)<<endl;
    cout<<sizeof(int32_t)<<endl;
    int num=6;
    char c='a';
    void test_num_Macro(num data){ cout<<"Test: "<<sizeof(data)<<" "<<endl;;

}

Thus said, you should (and probably, you already got it) use templates:

template <class Type>
void Query_Data(Type data) {
    std::cout << "Test: " << sizeof(data) << " " << std::endl;
}

If you wish, you can specialize the template for specific types like:

template<>
void Query_Data<int>(int data) {
    std::cout << "This is an integer!" << std::endl;
}

and use them as intended:

int main(){
    cout<<sizeof(unsigned)<<endl;
    cout<<sizeof(char)<<endl;
    cout<<sizeof(int32_t)<<endl;
    int num=6;
    char c='a';
    Query_Data(num);
    Query_Data(c);
}  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM