3

Consider the following (a bit conceived) example:

// a.cpp
int mystrlen(const char* a) {
   int l = 0;
   while (a[l]) ++l;
   return l;
}

// b.cpp
extern int mystrlen(const char*);
int foo(const char* text) {
   return mystrlen(text) + mystrlen(text);
}

It would be very nice to be able to tell the compiler that mystrlen() doesn't have side-effects and thus it can re-use the old result from mystrlen(text) instead of calling it twice.

I don't find anything in the docs about it and restrict or one of its variances doesn't seem to do the job, either. A look at the output code with all optimizations on (switch /Ox) shows that the compiler really generates two calls. It even does so if I put both functions in one module.

Any solution to this or can anyone confirm that there is no solution in VC++?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
cxxl
  • 4,939
  • 3
  • 31
  • 52

3 Answers3

2

MSVC has no support for pure/const attributes, and also has no intention to support them. See https://connect.microsoft.com/VisualStudio/feedback/details/804288/msvc-add-const-and-pure-like-function-attributes. Other compilers, such as GCC and Clang do support such attributes. Also see pure/const function attributes in different compilers.

Community
  • 1
  • 1
bcmpinc
  • 3,202
  • 29
  • 36
-1

Because C++ is an imperative language rather than a functional one, what you're trying to achieve is not possible.

It looks like the behaviour that you're expecting here is is that of referential transparency, which there isn't a way to tell the compiler about in C++ (but in a purely functional programming language like Haskell would be implicit).

Hopefully a future standard of C++ will introduce a keyword that will allow us to mark functions as 'pure' or 'without side effect'.

Salami
  • 1,048
  • 1
  • 10
  • 17
  • 2
    I don't see why imperative vs. functional have anything to do with being able to flag a certain function as having no side effects (i.e. consequences to other objects). Without doubt, it _can_ be implemented in C++. The question is, _is_ it? – cxxl Dec 29 '13 at 12:27
-1

What you are looking for won't help you.

In general, the compiler can't elide the calls, even if if believes the function is without side effects. Where did you get that pointer? Does a signal handler have access to that same pointer? Maybe another thread? How does the compiler know the memory pointed to by the pointer isn't going to change out from underneath it?

Compiler's do frequently eliminate redundant fetches within a function body, even for things fetched through pointers. But there is a limit to how much of this they can or even should do.

Here you're asking the compiler to believe that a bare pointer you have to who knows where will maintain consistent contents between two function calls. That's a lot of assuming. Sure you haven't declared your pointer volatile, but still, it's a lot of assuming.

Now, if you had a buffer on the stack and were passing it to that function twice in a row, the compiler can pretty safely assume that if you haven't passed the pointer out somewhere else that the contents of that buffer aren't going to be changed by some random other thing in the program at some unexpected time.

For example:

// b.cpp
extern int mystrlen(const char*);
int foo(int bar) {
   char number[20];
   snsprintf(number, 20, "%d", bar);
   return mystrlen(number) + mystrlen(number);
}

Given assumptions the compiler could make about what snprintf did with number given that it's a library function, it could then elide the second call to mystrlen if there was a way to declare the mystrlen had no side effects.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • A C++ compiler is allowed to engage in "as-if" execution. It can elide the entire program if it determines it has no side-effects, and just return the final integer value from main. – einpoklum Jun 18 '23 at 08:22