I am trying to dig into implications of a function being inline and stumbled upon this issue. Consider this small program (demo):
/* ---------- main.cpp ---------- */
void other();
constexpr int get()
{
return 3;
}
int main()
{
std::cout << get() << std::endl;
other();
}
/* ---------- other.cpp ---------- */
constexpr int get()
{
return 4;
}
void other()
{
std::cout << get() << std::endl;
}
When compiled without optimizations, the program yields the following output:
3
3
Which might be not what we want, but at least I can explain it.
The compiler is not required to compute results of constexpr functions on compile time, so it decided to postpone it to runtime.
constexpr on functions implies inline
Our get() functions happened to have different implementations
We did not declare get() functions static
The linker must chose only one implementation of the get() function
And it so happened that the linker chose get() from main.cpp, which returned 3.
Now to the part I don't get. I simply changed get() functions from constexpr to consteval. Now the compiler is required to compute the value during compile time, i.e. before the link time (right?). I'd expect get() functions not to be present in object files at all.
But when I run it (demo), I have exactly the same output! How can this be?.. I mean yes, I understand that this is undefined behavior, but this is not the point. How come that the values that should have been computed on compile time interfered with other translation unit?
UPD: I am aware that this feature is listed as unimplemented in clang, but the question is applicable anyway. Is a conformant compiler allowed to exhibit such a behavior?
A program with two definitions of the same inline function is an ill-formed program, no diagnostics required.
The standard places no requirements on the runtime or compile-time behavior of an ill-formed program.
Now, there is no "compile time" in C++ as you are imagining it. While almost every C++ implementation compiles files, links them, builds a binary, then runs it, the C++ standard tip-toes around this fact.
It talks about translation units, and what happens when you put them together into a program, and what that program's runtime behaviour is.
...
In practice, your compiler could be building a map from symbol to some internal structure. It is compiling your first file, and then in the second file it is still accessing that map. A new definition of the same inline function? Just skip it.
Second, your code must produce a compile time constant expression. But a compile time constant expression is not an observable property in the context where you used it, and there are no side effects to doing it at link or even run time! And under as-if there is nothing preventing that.
consteval is saying "if I run this and the rules that permit it being a constant expression are violated, I should error rather than fall back on non-constant expression". This is similar to "it must be run at compile time", but it is not the same.
To determine which of these is happening, try this:
template<auto x>
constexpr std::integral_constant< decltype(x), x > constant = {};
now replace your print lines with:
std::cout << constant<get()> << std::endl;
this makes putting off the evaluation to run/link time as impractical.
That will distinguish between the "compiler is being clever and caching get" from "compiler is evaluating it later at link time", because determining which ostream& << to call requires instantiating the type of constant<get()>, which in turn requires evaluating get().
Compilers tend not to defer overload resolution to link time.
The requirement for a consteval function is that every call to it must produce a constant expression.
Once the compiler satisfies itself that a call does produce a constant expression, there's no requirement that it must not codegen the function and call it at run time. Of course, for some consteval functions (like those envisioned for reflection) it had better not do that (at least if it doesn't want to put all its internal data structures into the object file), but that's not a general requirement.
Undefined behavior is undefined.
The answer to this is that it's still an ODR violation, no matter if the function is a constexpr or consteval. Maybe with a particular compiler and a particular code you may get the answer you're expecting, but it's still ill formed, no diagnostic required.
What you could do is to define them in anonymous namespaces:
/* ---------- main.cpp ---------- */
void other();
namespace {
constexpr int get()
{
return 3;
}
}
int main()
{
std::cout << get() << std::endl;
other();
}
/* ---------- other.cpp ---------- */
namespace {
constexpr int get()
{
return 4;
}
}
void other()
{
std::cout << get() << std::endl;
}
But even better, simply use modules:
/* ---------- main.cpp ---------- */
import other;
constexpr int get()
{
return 3;
}
int main()
{
std::cout << get() << std::endl; // print 3
other();
}
/* ---------- other.cpp ---------- */
export module other;
constexpr int get() // okay, module linkage
{
return 4;
}
export void other()
{
std::cout << get() << std::endl; // print 4
}
Related
What is the difference between std::invocable and std::regular_invocable? Based on the description from
https://en.cppreference.com/w/cpp/concepts/invocable I would expect that the std::regular_invocable concept doesn't allow to change the state of of the function object when it is called (or at least the result of the calling should always return the same result).
Why the code below compiles?
Compiled with a command: g++-10 -std=c++2a ./main.cc.
#include <iostream>
#include <concepts>
using namespace std;
template<std::regular_invocable F>
auto call_with_regular_invocable_constraint(F& f){
return f();
}
template<std::invocable F>
auto call_with_invocable_constraint(F& f){
return f();
}
class adds_one {
int state{0};
public:
int operator()() {
state++;
return state;
}
};
int main()
{
auto immutable_function_object([]() { return 1; });
adds_one mutable_function_object;
// I would expect only first three will be compiled and the last one will fail to compile because the procedure is
// not regular (that is does not result in equal outputs given equal inputs).
cout << call_with_invocable_constraint(immutable_function_object) << endl;
cout << call_with_invocable_constraint(mutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(immutable_function_object) << endl;
cout << call_with_regular_invocable_constraint(mutable_function_object) << endl; // Compiles!
}
Output of the program:
1
1
1
2
From the reference:
Notes
The distinction between invocable and regular_invocable is purely semantic.
This means that there is no way for the compiler to enforce the distinction through the concepts system, since that can only check syntactic properties.
From the introduction to the concepts library:
In general, only the syntactic requirements can be checked by the compiler. If the validity or meaning of a program depends whether a sequenced of template arguments models a concept, and the concept is satisfied but not modeled, or if a semantic requirement is not met at the point of use, the program is ill-formed, no diagnostic required.
Hypothetically, we could write:
template< class F, class... Args >
concept regular_invocable = invocable<F, Args...> &&
requires(F&& f, Args&&... args) {
auto prev = f;
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
assert(f == prev);
// TODO assert that `args` are unchanged
// TODO assert that invoking `f` a second time gives the same result
};
However, this would not actually test that the assertion holds, since a requires clause is not invoked at run time but only checked at compile time.
regular_invocable tells the user of the function that it will assume, that the result calling that regular_invocable function with the same value of the arguments will result in the same return value, and might cache that result due to that.
Caching the result could either be done by the function that expects regular_invocable or the compiler could use that information to optimize away multiple function calls to the regular_invocable function when the value of the arguments stay the same. So right now it can be seen as documentation and compiler hint.
Similar to const_cast it might not always be possible for the compiler to check if it is valid. Due to that and because there is currently not attribute/keyword in the standard to mark a function to always return the same value, there is right now no way to enforce at compile time that the function passed regular_invocable really matches that requirement.
I ran into a nasty bug in some of my code. Here's the simplified version:
#include <iostream>
class A
{
public:
std::string s;
void run(const std::string& x)
{
// do some "read-only" stuff with "x"
std::cout << "x = " << x << std::endl;
// Since I passed X as a const referece, I expected string never to change
// but actually, it does get changed by clear() function
clear();
// trying to do something else with "x",
// but now it has a different value although I declared it as
// "const". This killed the code logic.
std::cout << "x = " << x << std::endl;
// is there some way to detect possible change of X here during compile-time?
}
void clear()
{
// in my actual code, this doesn't even happen here, but 3 levels deep on some other code that gets called
s.clear();
}
};
int main()
{
A a;
a.s = "test";
a.run(a.s);
return 0;
}
Basically, the code that calls a.run() use to be used for all kinds of strings in the past and at one point, I needed the exact value that object "a.s" had, so I just put a.s in there and then some time later noticed program behaving weird. I tracked it down to this.
Now, I understand why this is happening, but it looks like one of those really hard to trace and detect bugs. You see the parameter declared as const & and suddenly it's value changes.
Is there some way to detect this during compile-time? I'm using CLang and MSVC.
Thanks.
Is there some way to detect this during compile-time?
I don't think so. There is nothing inherently wrong about modifying a member variable that is referred by a const reference, so there is no reason for the compiler to warn about it. The compiler cannot read your mind to find out what your expectations are.
There are some usages where such wrong assumption could result in definite bugs such as undefined behaviour that could be diagnosed if identified. I suspect that identifying such cases in general would be quite expensive computationally, so I wouldn't rely on it.
Redesigning the interface could make that situation impossible For example following:
struct wrapper {
std::string str;
};
void run(const wrapper& x);
x.str will not alias the member because the member is not inside a wrapper.
I try to code a simple way to execute code at start of the program automatically (without using not portable attribute()).
I wrote the following code, and I'm asking if it does violate the ODR if the code written before main() is put in header files.
Or, does the inline function and variable prevent that?
Would there be a case where the function would be called twice if the ODR is violated?
#include <iostream>
//-----
template <void(*init_function)()>
class execute_at_start
{
struct dummy final {};
~execute_at_start() = delete;
inline static dummy execute_() { init_function(); return dummy{}; }
inline static dummy auto_init_ = execute_();
};
//-----
inline void echo(){ std::cout << "echo" << std::endl; }
template class execute_at_start<&echo>;
int main()
{
std::cout << "EXIT SUCCESS" << std::endl;
return EXIT_SUCCESS;
}
Thank you in advance
Your solution should be ODR-safe. The C++ standard requires that there is only one instance of static data member auto_init_ for each distinct instantiation of execute_at_start<> class template and that it is initialized once.
Itanium C++ ABI (most compilers comply with it, apart from MSVC) requires guard variables for globals (auto_init_ here) to make sure they are initialized once:
If a function-scope static variable or a static data member with vague linkage (i.e., a static data member of a class template) is dynamically initialized, then there is an associated guard variable which is used to guarantee that construction occurs only once.
See Itanium C++ ABI ยง2.8 Initialization Guard Variables for more details.
Another standard ODR-safe solution for this problem that doesn't rely on guard variables is Schwarz Counter. It has been used to initialize the standard streams (std::cout and friends) since the dawn of C++. In this solution counter is an explicit guard variable that has external linkage and it makes sure only the first invocation of execute_at_start constructor calls init_function:
// Header begin.
#include <iostream>
template<void(*init_function)()>
class execute_at_start {
static inline int counter = 0;
public:
execute_at_start() {
if(!counter++)
init_function();
}
};
inline void echo() { std::cout << "echo" << std::endl; }
execute_at_start<echo> const execute_at_start_echo; // A copy in each translation unit.
// Header end.
int main() {}
Is there a way to know how many instructions or resources are used by a variable or object inside the compiled executable?
For example, I would like to know how much space an empty std::vector<int> will use in the compiled binary file.
Tell the compiler to generate an assembly listing (compiler/linker options, depends on your compiler and platform). Then compile it once with, and once without the variable or object. Compare the number of lines in the two generated listings. This should give you the difference of instruction count.
EDIT: The measurement might not be 100% accurate due to various optimizations, alignment, code reordering. As #Klaus pointed out, paradox results may be seen when inlining tresholds are exceeded and produce smaller listings from more source.
EDIT: specifically in connection with C++ templates, see also Can we see the template instantiated code by C++ compiler
(You mentioned "inside the compiled executable", so I assume that you were asking about compile-time, not runtime).
Authors of "C++ Templates The Complete Guide" book (6.6.4 chapter) suggested to use so called Tracer objects for similiar purposes.
It is quote:
"A tracer is a user-defined class that can be used as an argument for a template to be tested. Often, it is written just to
meet the requirements of the template and no more than those requirements. More important, however, a tracer
should generate a trace of the operations that are invoked on it. This allows, for example, to verify experimentally the
efficiency of algorithms as well as the sequence of operations."
Simple example of tracer object:
#include <iostream>
#include <vector>
class TracerObject
{
public:
TracerObject()
{
++n_created;
}
~TracerObject()
{
++n_destroyed;
}
static int created_count(void)
{
return n_created;
}
static int destroyed_count(void)
{
return n_destroyed;
}
private:
static int n_created;
static int n_destroyed;
};
int TracerObject::n_created = 0;
int TracerObject::n_destroyed = 0;
int main(void)
{
{
std::vector<TracerObject> vector(2, TracerObject());
}
std::cout << "Constructor calls: " << TracerObject::created_count() << std::endl;
std::cout << "Destructor calls: " << TracerObject::destroyed_count() << std::endl;
int i;
std::cin >> i;
return 0;
}
If I have a function A(), I am interested in finding a convenient method to create a function B() that has the exact same functionality as A(), differing only in name. The new function would be for a one-time use. The intent is to differentiate between calls to the same function in a somewhat primitive sampling profiler, and the duplicated function would only be used in this context. That is, it would never touch production code and only be used for tinkering.
First guess would be a macro that declares a function named B and creates an inlined call to A() inside of it. The problem here is that I'm not aware of a method in GCC to force an arbitrary function call to inline; it seems all inlining options are for function declarations rather than calls.
There may be some esoteric way to do it with templates, or possibly by tricking the compiler into inlining. I'm not sure it's possible. Any thoughts? Unfortunately the new C++ standard is not available, if it would make a difference.
Using templates
template<int x>
void A()
{
// ..
}
int main()
{
A<0>();
A<1>();
return 0;
}
Update
The compiler can be too smart and create only one body for A<0> and A<1>. At least Visual C++ 2010 does it in Release mode. To prevent it, just use the template parameter inside the function template body in logs or asserts. For example,
#include <iostream>
template<int x>
void A()
{
::std::cout << x << std::endl;
// ..
}
int main()
{
A<0>();
A<1>();
auto v0 = A<0>;
auto v1 = A<1>;
::std::cout << v0 << std::endl;
::std::cout << v1 << std::endl;
::std::cout << (v0 == v1) << std::endl;
return 0;
}
This works using templates:
#include <iostream>
template<typename T>
void foo() {
static int x = 0;
std::cout << &x << std::endl;
}
int main(int argc, char **argv) {
foo<int>();
foo<float>();
return 0;
}
If you execute that, you'll see two different values printed, reflecting the compiler generated code for both calls, even though the template parameter is unused. nm on the object file confirms this.
If this is a one-time debug hack, then why not:
#define A_CONTENT \
... // whatever
void A()
{
A_CONTENT
}
void B()
{
A_CONTENT
}
...
A(); // Call to A
B(); // Call to B
Macros are generally grim, but we're not talking about production code here, so who cares?
Having been down this road myself, the short answer is that even if you get the compiler to emit two identical duplicates of a function, the optimizing linker will notice that they're identical and fold them back together into one implementation. (And if you've turned off optimization in the linker, then your profile isn't valid anwyay).
In the context of a sampling profiler, I've found the easier approach is to make two tiny wrappers for the function instead:
void Func() { .... }
_declspec(noinline)
void A_Func( return Func(); }
void B_Func( return Func(); }
void C_Func( return Func(); }
Then when your profiler samples the callstack, you'll be able to differentiate between the different callsites of this function in a very straightforward way..
You could always define a macro, for example in Chromium we do the following to reuse code:
#define CHROMEG_CALLBACK_1(CLASS, RETURN, METHOD, SENDER, ARG1) \
static RETURN METHOD ## Thunk(SENDER sender, ARG1 one, \
gpointer userdata) { \
return reinterpret_cast<CLASS*>(userdata)->METHOD(sender, one); \
} \
\
virtual RETURN METHOD(SENDER, ARG1);
And we call them like:
CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnExposeEvent, GdkEventExpose*);
CHROMEGTK_CALLBACK_1(PageActionViewGtk, gboolean, OnButtonPressed, GdkEventButton*);
You can do something similar to do what you wanted. The above example shows us using two different implementations but with one common code base. For GTK callbacks.
It's a little unclear what you're really trying to do, but a really ugly solution would be to declare the body of A as a macro and then you can "inline" this macro within whatever functions you like.
Also, macros are evil. Never use them unless you really have to.
Why do you care so much about inlining it? If you create a wrapper function, there is a pretty good chance the compiler will inline it anyway. At the very least, you're unlikely to get a function frame constructed.
C++11 also lets you do this:
void A() {
...
}
...
auto B = [] () -> void { A(); };
You can now use B syntactically as though it was a function wrapping A.