0

I want to define (var-1) > 0? var - 1: 0 as a inline replace. such as

#define MAX(VAR) as (VAR-1) > 0? VAR- 1: 0

like using etc?

kometen
  • 6,536
  • 6
  • 41
  • 51
  • 9
    No, you don't want to define an inline replacement. What you want is a function, or possibly a function template. If someone passes an expression with side effects to your macro, those side effects might happen twice. – Caleth Nov 24 '21 at 09:17
  • @Caleth are macro defined in cpp acts globally on the project? or is it specifically to that cpp? – jojo_Aero_smith_the_dummy Nov 24 '21 at 09:20
  • 2
    If you are a beginner at C++, you are not in a position to second guess whether inlining a particular function is an optimisation or a pessimisation. Leave that up to the implementation. – Caleth Nov 24 '21 at 09:24
  • A macro replaces matching text that follows its definition (up to it's undefinition) – Caleth Nov 24 '21 at 09:25
  • "like `using` etc"? What does that mean? – molbdnilo Nov 24 '21 at 09:31

3 Answers3

6

You define a function, and leave it up to the implementation to appropriately inline it.

 constexpr int max(int var) { return (var - 1) > 0 ? (var - 1) : 0; }

Aside: max isn't a great name for this, I'd suggest something like clamp_positive

Caleth
  • 52,200
  • 2
  • 44
  • 75
1

You can use, well, the inline keyword:

inline int max(int var) 
{ 
    return (var - 1) > 0 ? (var - 1) : 0; 
}

But, this will not force the inline, it will just suggest the compiler that you should make this function inline. The compiler can refuse your suggest, or make it inline even if you don't use the inline keyword

0

The syntax is of #defines for preprocessors are simply

#define Name(...args) (replacement)

without as or =

So your definition would be

#define MAX(VAR) (VAR-1) > 0? VAR- 1: 0

In my experience I always find that it is useful to wrap defines like these with parenthesis to avoid ambiguity, you never know where this will be replace for instance MAX(x)*5 would give (x-1) > 0 ? x-1 : 0*5 that is the same as MAX(x).

#define MAX(VAR) ((VAR-1) > 0? VAR- 1: 0)

If you want to use a function as in suggested in the comments

int MAX(int v){
  return (v-1)>0? v-1:0;
}

Or as a template function

template<typename Tp>
Tp MAX(const _Tp &v){
  return (v-1)>0? v-1:0;
}
Bob
  • 13,867
  • 1
  • 5
  • 27
  • 1
    Identifiers starting with underscore and a capital letter are reserved for the implementation. Don't use them - there is an immense amount of other names to choose from. – molbdnilo Nov 24 '21 at 10:05
  • Thank you @molbdnilo, could you please point me a reference about these conventions, please? – Bob Nov 24 '21 at 11:01
  • It's not a convention, it is a hard rule specified in The Standard. – molbdnilo Nov 24 '21 at 11:44
  • Is the standard available on the web? – Bob Nov 24 '21 at 11:52
  • https://isocpp.org/? I never saw a standard that everybody refers to. I only read the compiler messages, and random internet pages. This is for me like the bible was to the medieval people. – Bob Nov 24 '21 at 12:00
  • I use the _Tp for template types precisely because it is how the STL methods do. – Bob Nov 24 '21 at 12:00
  • You shouldn't read random internet pages, you should read [books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). And the library implementation is not an example of what to do. Everything in there is an internal implementation detail. – molbdnilo Nov 24 '21 at 12:01
  • Sorry, in your previous comment you suggested me to use google, now you are suggesting books, but you never shown me where it says that I should not start with _[A-Z]. – Bob Nov 24 '21 at 12:15
  • I am not asking for books here, I only want you to show how is this rule stated. – Bob Nov 24 '21 at 12:24
  • See [here](https://eel.is/c++draft/lex.name). – molbdnilo Nov 24 '21 at 12:26
  • Thank you, so that means that, a compiler could extend the C++ language and assign a different meaning to any of those identifier? Code like [this](https://github.com/gcc-mirror/gcc/blob/6180f5c8d6d1dc7b6634c41a46f0f8f5ca2e5b9d/libstdc%2B%2B-v3/include/std/set#L90) are explicitly violating that specification, targeting code for one specific compiler? – Bob Nov 24 '21 at 12:36
  • The code you're looking at *is* "the implementation", which is explicitly allowed to do that (that's what "reserved to the implementation" means). Even if it weren't specifically allowed, the library implementation is allowed to do things that users of it aren't. – molbdnilo Nov 24 '21 at 12:43
  • 1
    @Bob -- the reason for using `_Tp` in the implementation is **exactly** that the name is reserved for use by the implementation. That protects the standard library headers from code that, say, does `#define _Tp my_type`, which would break the standard library headers. It also can go the other way; the standard library headers might define a macro for internal use, and you don't want to use the name of that macro in your code. – Pete Becker Nov 24 '21 at 13:52