using std::max causes a link error? - c++11

Consider a library that defines in a header file
struct Proj {
struct Depth {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
struct Video {
static constexpr unsigned Width = 10u;
static constexpr unsigned Height = 10u;
};
};
The library gets compiled, and I'm now developing an application that links against this library. I thought for a long time it was some kind of visibility problem, but even after adding B_EXPORT (standard visibility stuff from CMake) everywhere with no change, I finally found the problem.
template <class Projection>
struct SomeApplication {
SomeApplication() {
unsigned height = std::max(// or std::max<unsigned>
Projection::Depth::Height,
Projection::Video::Height
);
}
};
I can't even reproduce the problem with a small dummy library / sample application. But using std::max in the application causes the link error, whereas if I just do it myself
unsigned height = Projection::Depth::Height;
if (height < Projection::Video::Height)
height = Projection::Video::Height;
Everything works out. AKA there don't appear to be any specific issues with the visibility in terms of just using Projection::XXX.
Any thoughts on what could possibly cause this? This is on OSX, so this doesn't even apply.

The problem is that Width and Height are declared, not defined in your structs. Effectively, this means there is no storage allocated for them.
Now recall the signature for std::max:
template<typename T>
const T& max(const T&, const T&);
Note the references: this means the addresses of the arguments are to be taken. But, since Width and Height are only declared, they don't have any storage! Hence the linker error.
Now let's consider the rest of your question.
Your hand-written max works because you never take any pointers or references to the variables.
You might be unable to reproduce this on a toy example because, depending on the optimization level in particular, a sufficiently smart compiler might evaluate max at compile time and save the trouble of taking the addresses at runtime. For instance, compare the disasm for no optimization vs -O2 for gcc 7.2: the evaluation is indeed done at compile-time!
As for the fix, it depends. You have several options, to name a few:
Use constexpr getter functions instead of variables. In this case the values they return will behave more like temporary objects, allowing the addresses to be taken (and the compiler will surely optimize that away). This is the approach I'd suggest in general.
Use namespaces instead of structs. In this case the variables will also be defined in addition to being declared. The caveat is that you might get duplicate symbol errors if they are used in more than one translation unit. The fix for that is only in form of C++17 inline variables.
...speaking of which, C++17 also changes the rules for constexpr static member variables (they become inline by default), so you won't get this error if you just switch to this standard.

Related

How to debug if a constexpr function doesn't run on compile time?

For example I have a constexpr function, but I use a runtime variable (not marked as constexpr) to take the return value. In this case, I'm not sure whether the function runs on compile time or runtime, So is there any way to debug?
At first I thinked about static_assert, but it looks like static_assert cannot do this. Then I thought convert the code to assembly code, but it is way too difficult to check the assembly code to figure out.
Before C++20 there is no way to directly handle it from the program itself.
With C++20 you have std::is_constant_evaluated.
If the return type from your constexpr func is a valid non type template parameter, you can force your function to be evaluated in compile time like this:
constexpr int func( int x )
{
return x*2;
}
template < auto x >
auto force_constexpr_evaluation()
{
return x;
}
int main()
{
int y = force_constexpr_evaluation<func(99)>();
}
If you are using c++20 already, you can directly force compile time evaluation by using consteval
Debugging on assembly level should be not so hard.
If you see a function call to your constexpr func, it is running in run time.
If you see directly the forwarded value, it was evaluated in compile time.
If it is inlined, you should be able to detect it by having the function name associated from the debug symbols to the location of the inlined code. Typically, if you set a breakpoint on the constexpr function and it is not always be executed at compile time but inlined, you get a number of breakpoints not only a single one. Even if it is one, it points to the inlined position in that case.
BTW: It is not possible to back port std::is_constant_evaluated to older compilers, as it needs some implementation magic.

When should I use static data members vs. const global variables?

Declaring const global variables has proven useful to determine some functioning parameters of an API. For example, on my API, the minimum order of numerical accuracy operators have is 2; thus, I declare:
const int kDefaultOrderAccuracy{2};
as a global variable. Would it be better to make this a static const public data member of the classes describing these operators? When, in general, is better to choose one over the other?
const int kDefaultOrderAccuracy{2};
is the declaration of a static variable: kDefaultOrderAccuracy has internal linkage. Putting names with internal linkage in a header is obviously an extremely bad idea, making it extremely easy to violate the One Definition Rule (ODR) in other code with external linkage in the same or other header, notably when the name is used in the body of an inline or template function:
Inside f.hpp:
template <typename T>
const T& max(const T &x, const T &y) {
return x>y ? x : y;
}
inline int f(int x) {
return max(kDefaultOrderAccuracy, x); // which kDefaultOrderAccuracy?
}
As soon as you include f.hpp in two TU (Translation Units), you violate the ODR, as the definition is not unique, as it uses a namespace static variable: which kDefaultOrderAccuracy object the definition designates depends on the TU in which it is compiled.
A static member of a class has external linkage:
struct constants {
static const int kDefaultOrderAccuracy{2};
};
inline int f(int x) {
return max(constants::kDefaultOrderAccuracy, x); // OK
}
There is only one constants::kDefaultOrderAccuracy in the program.
You can also use namespace level global constant objects:
extern const int kDefaultOrderAccuracy;
Context is always important.
To answer questions like this.
Also for naming itself.
If you as a reader (co-coder) need to guess what an identifier means, you start looking for more context, this may be supported through an API doc, often included in decent IDEs. But if you didn't provide a really great API doc (I read this from your question), the only context you get is by looking where your declaration is placed.
Here you may be interested in the name(s) of the containing library, subdirectory, file, namespace, or class, and last not least in the type being used.
If I read kDefaultOrderAccuracy, I see a lot of context encoded (Default, Order, Accuracy), where Order could be related for sales or sorting, and the k encoding doesn't say anything to me. Just to make you looking on your actual problem from a different perspective. C/C++ Identifiers have a poor grammar: they are restricted to rules for compound words.
This limitation of global identifiers is the most important reason why I mostly avoid global variables, even constants, sometimes even types. If its the meaning is limited to a given context, define a thing right within this context. Sometimes you first have to create this context.
Your explanation contains some unused context:
numerical operators
minimum precision (BTW: minimum doesn't mean default)
The problem of placing a definition into the right class is not very different from the problem to find the right place for a global: you have to find/create the right header file (and/or namespace).
As a side note, you may be interested to learn that also enum can be used to get cheap compile-time constants, and enums can also be placed into classes (or namespaces). Also a scoped enumeration is an option you should consider before introducing global constants. As with enclosing class definitions, the :: is a means of punctuation which separates more than _ or an in-word caseChange.
Addendum:
If you are interested in providing a useful default behaviour of your operations that can be overridden by your users, default arguments could be an option. If your API provides operators, you should study how the input/output manipulators for the standard I/O streams work.
my guess is that:
const takes up inline memory based on size of data value such as “mov ah, const value” for each use, which can be a really short command, in size overall, overall, based on input value.
whereas static values takes up a whole full data type, usually int, whatever that maybe on the current system for each static, maybe more, plus it may need a full memory access value to access the data, such as mov ah, [memory pointer], which is usually size of int on the system, for each use (with a full class it could even more complex). yet the static is still declared const so it may behave the same as the normal const type.

How to define a constexpr variable

I want to use a simple compile time constant for example like this:
double foo(double x) { return x + kConstDouble; }
Now I see at least the following ways to define that constant
namespace { static constexpr double kConstDouble = 5.0; }
namespace { constexpr double kConstDouble = 5.0; }
static constexpr double kConstDouble = 5.0;
constexpr double kConstDouble = 5.0;
Which is the right way to go? Is there a difference when kConstDouble is defined in a header vs a source file?
Using static or an anonymous namespace will cause the variable to have internal linkage; it will only be visible within the same translation unit. So if you use one of these within a .cpp file, you won't be able to use the variable anywhere else. This would be done typically if the constant is an implementation detail of that unit of code. If you want to expose it to other translation units, you'll need to put it in a header file. The typical way to do that would be to declare it static (or put it in anonymous namespace), since it is a trivial and constant variable. The other approach would be to declare it extern in the header, and define it in the .cpp to get a truly global variable (as opposed top one where actually every tu has its own copy).
Between static and anonymous namespace; well you don't need both first of all. They both do the same thing AFAIK. But I think it is more idiomatic at this point to use anonymous namespaces in cpp files, as they can be used to also give functions, classes, etc internal linkage. On the other hand, when you want to use it for making a variable globally available, it's more common to use static; I never use anonymous namespaces in header files as I find it misleading.

Why can't declaration-only friend functions have default arguments?

I've learned that the C++11 standard doesn't allow friend functions to have default arguments unless the friend declaration is a definition. So this isn't allowed:
class bar
{
friend int foo(int seed = 0);
};
inline int foo(int seed) { return seed; }
but this is:
class bar
{
friend int foo(int seed = 0)
{
return seed;
}
};
(Example courtesy http://clang-developers.42468.n3.nabble.com/Clang-compile-error-td4033809.html)
What is the rational behind this decision? Friend functions with default arguments are useful, e.g. if the function is too complex to declare in place, why are they now disallowed?
In looking at DR 136, it looks like there are issues when a friend declaration combines with namespace-level declarations with default arguments that makes the semantics hard to reason about (and perhaps difficult to issue quality diagnostics against), especially in the context of templates. The proposed DR resolution given on that page is to only allow default arguments in them when the declaration is the only one in the program. Since a function definition is also a declaration, that would mean the only useful way to specify default arguments in a friend declaration is to make it a definition. I would guess the C++11 standard simply chose to make this practical usage requirement explicit.
(Technically, if by "program" they mean "translation unit", one could construct a complete program where the function were defined in a completely different translation unit, but since this function's definition would not have the class definition visible, the benefits of the friendship grant would be largely useless.)
The workaround for this hiccup seems pretty straightforward. Declare the friend without using default arguments, and then declare it again at namespace scope with whatever default arguments are desired.

unordered_map pointing to vector

I have some custom classes: LocationInfo (information about a location), and Coordinates (two ints specifying an X & Y grid location). I'm using an unordered_map to key a Coordinates object to a vector of LocationInfo objects:
typedef std::vector<LocationInfo> LocationVector;
...
std::unordered_map<Coordinates, LocationVector> data;
// I also tried:
// std::unordered_map<Coordinates, std::vector<LocationInfo> > data;
Upon linking, I get a very long error (two actually) that ends with:
undefined reference to `std::hash<Coordinates>::operator()(Coordinates) const'
I'm using g++4.6.1 with the -std=c++0x option on Ubuntu 11.10. After reading some posts on here, I originally thought there might be an issue requiring me to explicitly use typename before one of the types in the declaration. But I've only seen a need for that when using templates that confuse the compiler. I added some in just in case, and that only made matters worse.
You have to implement a custom hash functor for your types.
Look here unordered_map hash function c++ to see how it can be done.

Resources