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

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.

Related

C++11 Aggregate initialization of private member, is it correct?

Is it correct to initialize private member through aggregate initialization while passing it as a parameter into owner's class function? Just look at code below.
class A {
struct S {
int t, u;
};
public:
void f(const S& s) {}
};
int main() {
A a;
a.f({1, 2}); // correct?
return 0;
}
I checked standard and nets and it seems that there is no exact answer. Looks like mechanics are as follows:
* braced initializer is public thing and thus user doesn't violate access restrictions.
* implicit conversion from initializer into "S" is internal for "S" and thus also fine for compiler.
The question is, whether there is some reference in standard, draft or at least cppreference with the description of this behaviour?
Yes this is correct. The only thing private about S is the name. Access control only controls access through the name ([class.access]p4). So you could use a type trait to get the type of S for example through f's type (example).
So, it is allowed because there is no restriction [dcl.init.agg] that prohibits initializing "private" types.
There is also a note, found by #StephaDyatkovskiy.
It doesn't matter whether it's officially valid; you should avoid this corner case.
I would claim that "is it valid C++" is the wrong question here.
When you look at a piece of code and, try as you might, you can't decide whether it should be valid C++ or not; and you know it's going to be some corner case depending on the exact wording of the standard - it's usually a good idea not to rely on that corner case, either way. Why? Because other people will get confused too; they will waste time trying to figure out what you meant; they will go look it up in the standard - or worse, not look it up, and make invalid assumptions; and they will be distracted from what they actually need to focus on.
So, with this code, I would ask myself: "Is type S really private? Does outside code really not need to know about it?"
If the answer is "Yes, it is" - then I would change f, to take the parameters for an S constructor (and forward them to the ctor):
void f(int t, int u) { S {t, u}; /* etc. etc. */ }
If the answer is "No, code calling f() can know that it's passing an S reference" - then I would make S public.

Passing the same variable through intermediate methods which don't directly process it

More than often I find myself passing a variable into a method, where it is not directly used, but is yet passed to another method for further processing. I don't know if there is a name for this practice either. I can explain it better with a sample code:
static void main() {
int a = method1(var1, var2, var3)
}
int method1(int var1, int var2, int var3) {
var4 = some_function_of(var1, var2)
return method2(var3, var4)
}
int method2(int var 3, int var4) {
return some_other_function_of(var3, var4)
}
This case can be expanded where there the same variable (var3) is passed through even longer chains of methods. I think this could be a bad practice, as in my example method1 is some sort of intermediate that is not manipulating var3. Is there a better practice for performance, design and/or readability?
At least for object oriented languages the answer would be:
You definitely want to avoid such code - as you struggle to reduce your parameter list to the absolut minimum; the goal is zero.
If you find that your class should offer various methods that all require the "same" parameter; than that makes that parameter a candidate to be a field within your class.
In non-oo languages, I think you have to pragmatically balance between having more functions and parameter list length. In your example,
static void main() {
int var4 = some_function_of(var1, var2)
int a = method2(var3, var4)
}
avoiding method1 ... saves you passing var3 to your first method. And you are still within the rules of the "single layer of abstraction" principle.
This is not at all uncommon and not necessarily a bad practice. It can impact all three of the metrics you mentioned though:
Performance: Adding another parameter to a function call may result in a performance hit but not always. It depends on the language, compiler/interpreter, and platform. For example, an optimizing compiler for C++ will try to avoid copying a variable even if it is passed by value if it can (sometimes it will eliminate a function call completely). But passing a value through multiple functions might mess up the compiler's optimizations if it can't follow the path well. Still, I expect any performance hit from this to be minimal.
Design: Depending on your language's paradigm (object oriented, functional, etc...) this might indicate that your design could be improved, perhaps by encapsulating the data in a structure or class so that only one parameter is passed (a class instance pointer) and each function accesses only the class members it needs.
Readability: This shouldn't make the individual functions harder to read, since they shouldn't care where parameters come from and it is clear that the parameter is being passed to another function. It could make it harder to understand the whole program though because it can be hard to keep track of where values originate if they are passed through a long chain of calls before being touched.
In general, it is good to minimize the parameter list (for all of these reasons) and to keep data "closer" to code that needs it. If you do those things, this case shouldn't pop up much and when it does it will be less likely to be due to bad design.

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.

Avoiding self assignment in std::shuffle

I stumbled upon the following problem when using the checked implementation of glibcxx:
/usr/include/c++/4.8.2/debug/vector:159:error: attempt to self move assign.
Objects involved in the operation:
sequence "this" # 0x0x1b3f088 {
type = NSt7__debug6vectorIiSaIiEEE;
}
Which I have reduced to this minimal example:
#include <vector>
#include <random>
#include <algorithm>
struct Type {
std::vector<int> ints;
};
int main() {
std::vector<Type> intVectors = {{{1}}, {{1, 2}}};
std::shuffle(intVectors.begin(), intVectors.end(), std::mt19937());
}
Tracing the problem I found that shuffle wants to std::swap an element with itself. As the Type is user defined and no specialization for std::swap has been given for it, the default one is used which creates a temporary and uses operator=(&&) to transfer the values:
_Tp __tmp = _GLIBCXX_MOVE(__a);
__a = _GLIBCXX_MOVE(__b);
__b = _GLIBCXX_MOVE(__tmp);
As Type does not explicitly give operator=(&&) it is default implemented by "recursively" applying the same operation on its members.
The problem occurs on line 2 of the swap code where __a and __b point to the same object which results in effect in the code __a.operator=(std::move(__a)) which then triggers the error in the checked implementation of vector::operator=(&&).
My question is: Who's fault is this?
Is it mine, because I should provide an implementation for swap that makes "self swap" a NOP?
Is it std::shuffle's, because it should not try to swap an element with itself?
Is it the checked implementation's, because self-move-assigment is perfectly fine?
Everything is correct, the checked implementation is just doing me a favor in doing this extra check (but then how to turn it off)?
I have read about shuffle requiring the iterators to be ValueSwappable. Does this extend to self-swap (which is a mere runtime problem and can not be enforced by compile-time concept checks)?
Addendum
To trigger the error more directly one could use:
#include <vector>
int main() {
std::vector<int> vectorOfInts;
vectorOfInts = std::move(vectorOfInts);
}
Of course this is quite obvious (why would you move a vector to itself?).
If you where swapping std::vectors directly the error would not occur because of the vector class having a custom implementation of the swap function that does not use operator=(&&).
The libstdc++ Debug Mode assertion is based on this rule in the standard, from [res.on.arguments]
If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument.
i.e. the implementation can assume that the object bound to the parameter of T::operator=(T&&) does not alias *this, and if the program violates that assumption the behaviour is undefined. So if the Debug Mode detects that in fact the rvalue reference is bound to *this it has detected undefined behaviour and so can abort.
The paragraph contains this note as well (emphasis mine):
[Note: If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g., by calling the function with the argument
std::move(x)), the program is effectively asking that function to treat that lvalue as a temporary object. The implementation is free to optimize away aliasing checks which might be needed if the
argument was an lvalue. —end note]
i.e. if you say x = std::move(x) then the implementation can optimize away any check for aliasing such as:
X::operator=(X&& rval) { if (&rval != this) ...
Since the implementation can optimize that check away, the standard library types don't even bother doing such a check in the first place. They just assume self-move-assignment is undefined.
However, because self-move-assignment can arise in quite innocent code (possibly even outside the user's control, because the std::lib performs a self-swap) the standard was changed by Defect Report 2468. I don't think the resolution of that DR actually helps though. It doesn't change anything in [res.on.arguments], which means it is still undefined behaviour to perform a self-move-assignment, at least until issue 2839 gets resolved. It is clear that the C++ standard committee think self-move-assignment should not result in undefined behaviour (even if they've failed to actually say that in the standard so far) and so it's a libstdc++ bug that our Debug Mode still contains assertions to prevent self-move-assignment.
Until we remove the overeager checks from libstdc++ you can disable that individual assertion (but still keep all the other Debug Mode checks) by doing this before including any other headers:
#include <debug/macros.h>
#undef __glibcxx_check_self_move_assign
#define __glibcxx_check_self_move_assign(x)
Or equivalently, using just command-line flags (so no need to change the source code):
-D_GLIBCXX_DEBUG -include debug/macros.h -U__glibcxx_check_self_move_assign '-D__glibcxx_check_self_move_assign(x)='
This tells the compiler to include <debug/macros.h> at the start of the file, then undefines the macro that performs the self-move-assign assertion, and then redefines it to be empty.
(In general defining, undefining or redefining libstdc++'s internal macros is undefined and unsupported, but this will work, and has my blessing).
It is a bug in GCC's checked implementation. According to the C++11 standard, swappable requirements include (emphasis mine):
17.6.3.2 §4 An rvalue or lvalue t is swappable if and only if t is swappable with any rvalue or lvalue, respectively, of type T
Any rvalue or lvalue includes, by definition, t itself, therefore to be swappable swap(t,t) must be legal. At the same time the default swap implementation requires the following
20.2.2 §2 Requires: Type T shall be MoveConstructible (Table 20) and MoveAssignable (Table 22).
Therefore, to be swappable under the definition of the default swap operator self-move assignment must be valid and have the postcondition that after self assignment t is equivalent to it's old value (not necessarily a no-op though!) as per Table 22.
Although the object you are swapping is not a standard type, MoveAssignable has no precondition that rv and t refer to different objects, and as long as all members are MoveAssignable (as std::vector should be) the generate move assignment operator must be correct (as it performs memberwise move assignment as per 12.8 §29). Furthermore, although the note states that rv has valid but unspecified state, any state except being equivalent to it's original value would be incorrect for self assignment, as otherwise the postcondition would be violated.
I read a couple of tutorials about copy constructors and move assignments and stuff (for example this). They all say that the object must check for self assignment and do nothing in that case. So I would say it is the checked implementation's fault, because self-move-assigment is perfectly fine.

What is the best syntax to declare a class as noncopyable?

(assuming I cannot use boost::noncopyable, which was explicitly designed for that purpose)
(assuming I cannot use C++11)
When making a class noncopyable, I usually see the following syntax:
class MyClass
{
public:
...
stuff
...
private:
MyClass(const MyClass&); // disables the copy constructor
MyClass& operator=(const MyClass&); // disables the copy assignment operator
};
This syntax seems long-winded. I think that I can use the following instead:
MyClass(MyClass&); // disables the copy constructor
void operator=(MyClass); // disables the copy assignment operator
This seems shorter (it repeats the name of the class just 3 times instead of 4 times; it also omits const and &).
Does my syntax do exactly the same thing as the other syntax?
Is there any reason to prefer one over the other?
Putting the emphasize on shortening the source code a few words is not very good. Besides, you are making your operator= unreadible, it is no copy-operator anymore...
You should refrain from using the latter just to save a few words.
There is a post here, stating
//QUOTE
class MyClass
{
private:
MyClass(const MyClass&) {}
MyClass& operator=(const MyClass&) {}
};
If you are a C++ programmer who has read an introductory text on C++, but has little exposure to idiomatic C++ (ie: a lot of C++ programmers), this is... confusing. It declares copy constructors and copy assignment operators, but they're empty. So why declare them at all? Yes, they're private, but that only raises more questions: why make them private?
To understand why this prevents copying, you have to realize that by declaring them private, you make it so that non-members/friends cannot copy it. This is not immediately obvious to the novice. Nor is the error message that they will get when they try to copy it.
//QUOTE END

Resources