-3

I have following piece of code where I am using a macro for checking if element is present in the vector or not.

#define x.contains(a) x.find(a)!=x.end()
void main(){
     vector<int> v = {1,2,3,4};
     if(v.contains(2))
         cout<<"yes"<<endl;
     else
         cout<<"no"<<endl;
}

But on compilation it gives following error:

ISO C++11 requires whitespace after the macro name #define x.contains(a) x.find(a)!=x.end()

Please show me a way out. Thanks.

underscore_d
  • 6,309
  • 3
  • 38
  • 64
  • 6
    _"Please show me a way out."_ Use templated functions, not macros. Macros are never the answer. (*where never means occasionally, but not for 99.999% of users) – underscore_d Dec 21 '17 at 14:42
  • 4
    Using a macro for this is a bad idea to begin with. Just write a proper function. – Baum mit Augen Dec 21 '17 at 14:42
  • You can not add members to classes through macros like that. And you should really try to avoid macros in general. A simple templated `inline` function would be much better. – Some programmer dude Dec 21 '17 at 14:42
  • 2
    Don't write `void main()`. Have a look: https://stackoverflow.com/questions/636829/difference-between-void-main-and-int-main – Aditi Rawat Dec 21 '17 at 14:42
  • Macros always have syntax `name(arg1, arg2, ..., argn)` (or just `name`). Name can only contain `a-zA-Z0-9_`. You can't just put `x.` in there and expect it to work. Write a template function instead. – HolyBlackCat Dec 21 '17 at 14:43
  • Possible duplicate of [C++ Pass any container to function](https://stackoverflow.com/questions/27359791/c-pass-any-container-to-function) – underscore_d Dec 21 '17 at 14:43
  • 1
    It could work if you define it as contains(x, a), but never this way – leyanpan Dec 21 '17 at 14:47
  • 1
    On an unrelated note, if you want to be more generic and allow any container, then you should really use [`std::find`](http://en.cppreference.com/w/cpp/algorithm/find) instead. – Some programmer dude Dec 21 '17 at 14:55

1 Answers1

2

Macros are not the solution anymore.

If you want nevertheless to pursue in this direction, you need to make your macro look like a function instead of a member function, and also use sole parentheses to avoid unexpected effects related to operator precedence:

#define contains(x,a) ((x).find(a)!=(x).end())

But if you go this way, it would be a pity not to use C++ templates instead of the macros. For example:

template <class T, class U> 
bool contains (const T& x, U a) {
    return x.find(a)!=x.end();
}

One huge advantage of templates over macros, is the possibility to define specializations. The compiler then choses the most suitable implementation. For instance, neither the macro version nor my previous example can work with <list>, because there's no find() member function. But with templates, you can define a more specialized version :

template <class U>
bool contains (const list<U>& x, U a) {
    return std::find(x.begin(), x.end(), a)!=x.end();
}

Online demo

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • To add, for the reasons not to use macros check out this post: https://stackoverflow.com/questions/14041453/why-are-preprocessor-macros-evil-and-what-are-the-alternatives – Carlos Dec 21 '17 at 15:27
  • 1
    @Carlos Thanks for this additional reference. In the meantime I added a very specific and concrete argument, if OP wants to use `contains` on a `list` – Christophe Dec 21 '17 at 15:40