Why does `std::unary_function` still compile in c++17? - c++

The std::unary_function feature was deprecated in c++11 and deleted in c++17. But with the c++17 compiler flag, this code still compiles:
struct less_than_7 : std::unary_function<int, bool>
{
bool operator()(int i) const { return i < 7; }
};
Built with g++ -std=c++17 -O0 -Wall -pedantic main.cpp here.
Is a feature deletion optional for a compiler to implement?

Since it's no longer part of the C++17 standard its inclusion in one of your source code files falls into the same category as code that introduces things into std.
In other words, the program behaviour is undefined.
The program working is a manifestation of that undefined behaviour. And perhaps your implementation defines that undefined behaviour. But even so, your code is not portable C++17.

While it's nice to have standards, and multiple versions of those standards, the reality is that different toolchains have different levels of compliance.
This may involve delays implementing new features, delays implementing changes, or delays removing things.
This is simply a case of the latter.
VS 2019 has removed std::unary_function, but neither libstdc++ nor libc++ has yet. That's just how it is!

I'm trying to find the appropriate wording, but implementations do have a lot of leeway in adding extra names to std. That's a major reason why you can't - the two names might clash.
In particular, the existing implementation can have helper classes in std. Thus std::unary_function might have become merely a helper template for this particular implementation.

Related

pack fold expression (c++17 extension) available when building with c++14

The following code contains a fold expression, which afaiu is a c++17 feature:
template <typename... T> static bool variable_length_or(const T ... v) {
return (v || ...);
}
bool foo () {
return variable_length_or(true, false, true, false);
}
what I find odd is that both g++ and clang++ seem to be fine with it when building with -std=c++14 (compiler-explorer). They do create a warning:
<source>:2:16: warning: pack fold expression is a C++17 extension [-Wc++17-extensions]
return (v || ...);
This somewhat indicates that what I'm writing is not okay before c++17, but the compilation succeeds and the code seems to do what it should. I would've expected the compilation to fail.
Any explanation about why the compiler accepts my fold expression?
(credit where credit is due: I took inspiration from this question, and I could check if all T are bool similar to what is suggested here)
A conforming C++17 compiler has to provide fold expressions. But that's a useful language feature, is it worth actively disabling it just because you're compiling in a previous language mode?
Implementations are allowed to provide extensions, provided that they do not alter the behavior of well-formed programs ([intro.compliance]/8). Fold expressions in pre-C++17 are just such an extension - they're purely additive. So as a question of utility tradeoff between allowing and disallowing fold expressions in C++14 mode, it seems that both gcc and clang decided to lean towards allowing.
Of course, you shouldn't rely on this - if you want to write C++17 code, you should compile in C++17. If you want help relying on it, you can compile with -pedantic-errors:
Give an error whenever the base standard (see -Wpedantic) requires a diagnostic, in some cases where there is undefined behavior at compile-time and in some other cases that do not prevent compilation of programs that are valid according to the standard. This is not equivalent to -Werror=pedantic, since there are errors enabled by this option and not enabled by the latter and vice versa.
If you don't add something as -ansi -pedantic, to impose a strict conformance to the standard, the compilers are free to adopt some extensions or, in this case, elements of the following standard.
-ansi -pedantic are the options I add for g++ and clang++; other compilers can use different options, obviously.
-- EDIT --
As pointed by Barry (thanks!), -ansi is no more useful and is enough -pedantic.
As pointed by Passer By (thanks!), can be useful the use of -pedantic-error to impose an error, and non only a warning, in case of not strictly conformance.

Is operator void*() conversion still part of C++ library?

Consider this program:
#include <iostream>
int main()
{
delete std::cout;
}
AFAIK the conversion function operator void* () const has been removed from C++11. So, this program should fail in compilation on a C++11 compiler. Ya, its true that both g++ 4.8.1 & 4.9.2 gives diagnosis (in the form of warning that deleting void* is undefined & that's also the good thing). But shouldn't this program fail in compilation because removal of that conversion function due to which all stream object could be implicitly converted to void* in C++98 & C++03?. Is this bug? It seems bit surprising that they still not have implemented this change.
I've tried this program in g++ 4.9.2(that supports C++14) but it gives warning not compiler error. Ideone compiler gives me an error as expected. (See live demo here)
It has nothing to do with the compiler, its a library issue. libstdc++ has lots of incompatibilities with C++11, of which this is just one. They are making breaking changes in 5 and up though iirc.
In short, it's neither a bug nor a compiler issue.
This is a bug in the standard library (if you view it as an implementation of the C++11/14 standard library rather than C++98/03).
It's sort of a compiler issue as well though. Specifically, removing the conversion to void * depends on adding a conversion directly to bool--but that, in turn, depends on adding "contextual conversion" to the compiler.
gcc 4.8 did implement a form of contextual conversion, but not the form that was accepted into the standard. Although the specific changes to contextual conversion wouldn't directly impact this use of contextual conversion, it does point to the fact that the definition of contextual conversion was still being tweaked as these compilers were being written.
The sequence in which things (at least normally) happen is that first the specification is solidified. Then the compiler implements it. Then the standard library puts it to use.
In this case the specification was still changing fairly shortly before the compiler was released. Therefore, the standard library didn't (and practically speaking, couldn't) use it.
By the time of 4.9, the specification was solid, and the compiler implemented the final version of contextual conversion, but it hadn't been around long enough to be put to use in the standard library yet.

Is it a conforming compiler extension to treat non-constexpr standard library functions as constexpr?

gcc compiles the following code without warning:
#include <cmath>
struct foo {
static constexpr double a = std::cos(3.);
static constexpr double c = std::exp(3.);
static constexpr double d = std::log(3.);
static constexpr double e1 = std::asin(1.);
static constexpr double h = std::sqrt(.1);
static constexpr double p = std::pow(1.3,-0.75);
};
int main()
{
}
None of the standard library functions used above are constexpr functions, we are allowed to use them where a constant expression is required from both the draft C++11 standard and draft C++14 standard section 7.1.5 [dcl.constexpr]:
[...]If it is initialized by a constructor call, that call shall be a
constant expression (5.19). Otherwise, or if a constexpr specifier is
used in a reference declaration, every full expression that appears in
its initializer shall be a constant expression.[...]
Even when using -std=c++14 -pedantic or -std=c++11 -pedantic no warnings are generated (see it live). Using -fno-builtin produces errors (see it live) which indicates that the builtin version of these standard library functions are being treated as if they where constexpr
While clang does not allow the code with any combination of flags I have tried.
So this is a gcc extension to treat at least some builtin functions as if they were constexpr functions even though the standard does not explicitly require them to be. I would have expected to at least receive a warning in strict conformance mode, is this a conforming extension?
TL;DR
In C++14 this is explicitly not allowed, although in 2011 it appeared like this case would be explicitly allowed. It is unclear if for C++11 this fell under the as-if rule, I don't believe it does since it alters observable behavior but that point was not clarified in the issue I reference below.
Details
The answer to this question has shifted with the evolving status of LWG issue 2013 which opens with:
Suppose that a particular function is not tagged as constexpr in the
standard, but that, in some particular implementation, it is possible
to write it within the constexpr constraints. If an implementer tags
such a function as constexpr, is that a violation of the standard or
is it a conforming extension?
In C++11 it was unclear if the as-if rule permitted this but the orignal proposal would have explicitly allowed it once it was accepted and we can see below in the gcc bug report I reference, this was the assumption made by the gcc team.
The consensus to allow this shifted in 2012 and the proposal changed and in C++14 this is a non-conforming extension. This is reflected in the draft C++14 standard section 17.6.5.6 [constexpr.functions] which says:
[...]An implementation shall not declare any standard library function
signature as constexpr except for those where it is explicitly
required.[..]
and although a strict reading of this seems to leave some wiggle room for treating a builtin implicitly as if it were a constexpr we can see from the following quote in the issue that the intention was to prevent divergence in implementations since identical code could produce different behavior when using SFINAE (emphasis mine):
Some concern expressed when presented to full committee for the vote
to WP status that this issue had been resolved without sufficient
thought of the consequences for diverging library implementations, as
users may use SFINAE to observe different behavior from otherwise
identical code.
We can see from the gcc bug report [C++0x] sinh vs asinh vs constexpr that the team relied on the earlier proposed resolution of LWG 2013 which says:
[...]Additionally, an implementation may declare any function to be
constexpr if that function's definition satisfies the necessary
constraints[...]
when deciding whether this change for the math functions was allowed in strict conformance mode.
As far as I can tell this would become conforming if this we received a warning in strict conformance mode i.e. using -std=c++11 -pedantic or if it was disabled in this mode.
Note, I added a comment to the bug report explaining that the resolution changed since this issue was originally addressed.
Jonathan Wakely pointed out in another question a more recent discussion and it seems likely the gcc bug report will be reopened to address this conformance issue.
What about intrinsics
Compiler intrinsics are not covered by the standard and so as far as I can tell they should be exempt from this rule, so using:
static constexpr double a = __builtin_cos(3.);
should be allowed. This question came up in the bug report and opinion of Daniel Krügler was:
[...]Library functions and other intrinsics can probably be considered as
exceptions, because they are not required to be "explainable" by
normal language rules.

GCC pragma to add/remove compiler options in a source file

I have developed a cross-platform library which makes fair use of type-punning in socket communications. This library is already being used in a number of projects, some of which I may not be aware of.
Using this library incorrectly can result in dangerously Undefined Behavior. I would like to ensure to the best of my ability that this library is being used properly.
Aside from documentation of course, under G++ the best way I'm aware of to do that is to use the -fstrict_aliasing and -Wstrict-aliasing options.
Is there a way under GCC to apply these options at a source file level?
In other words, I'd like to write something like the following:
MyFancyLib.h
#ifndef MY_FANCY_LIB_H
#define MY_FANCY_LIB_H
#pragma (something that pushes the current compiler options)
#pragma (something to set -fstrict_aliasing and -Wstrict-aliasing)
// ... my stuff ...
#pragma (something to pop the compiler options)
#endif
Is there a way?
I rather dislike nay-sayers. You can see an excellent post at this page: https://www.codingame.com/playgrounds/58302/using-pragma-for-compile-optimization
All the other answers clearly have nothing to do with the question so here is the actual documentation for GCC:
https://gcc.gnu.org/onlinedocs/gcc/Pragmas.html
Other compilers will have their own methods so you will need to look those up and create some macros to handle this.
Best of luck. Sorry that it took you 10 years to get any relevant answer.
Let's start with what I think is a false premise:
Using this library incorrectly can result in dangerously Undefined Behavior. I would like to ensure to the best of my ability that this library is being used properly.
If your library does type punning in a way that -fstrict-aliasing breaks, then it has undefined behavior according to the C++ standard regardless of what compiler flags are passed. The fact that the program seems to work on certain compilers when compiled with certain flags (in particular, -fno-strict-aliasing) does not change that.
Therefore, the best solution is to do what Florian said: change the code so it conforms to the C++ language specification. Until you do that, you're perpetually on thin ice.
"Yes, yes", you say, "but until then, what can I do to mitigate the problem?"
I recommend including a run-time check, used during library initialization, to detect the condition of having been compiled in a way that will cause it to misbehave. For example:
// Given two pointers to the *same* address, return 1 if the compiler
// is behaving as if -fstrict-aliasing is specified, and 0 if not.
//
// Based on https://blog.regehr.org/archives/959 .
static int sae_helper(int *h, long *k)
{
// Write a 1.
*h = 1;
// Overwrite it with all zeroes using a pointer with a different type.
// With naive semantics, '*h' is now 0. But when -fstrict-aliasing is
// enabled, the compiler will think 'h' and 'k' point to different
// memory locations ...
*k = 0;
// ... and therefore will optimize this read as 1.
return *h;
}
int strict_aliasing_enabled()
{
long k = 0;
// Undefined behavior! But we're only doing this because other
// code in the library also has undefined behavior, and we want
// to predict how that code will behave.
return sae_helper((int*)&k, &k);
}
(The above is C rather than C++ just to ease use in both languages.)
Now in your initialization routine, call strict_aliasing_enabled(), and if it returns 1, bail out immediately with an error message saying the library has been compiled incorrectly. This will help protect end users from misbehavior and alert the developers of the client programs that they need to fix their build.
I have tested this code with gcc-5.4.0 and clang-8.0.1. When -O2 is passed, strict_aliasing_enabled() returns 1. When -O2 -fno-strict-aliasing is passed, that function returns 0.
But let me emphasize again: my code has undefined behavior! There is (can be) no guarantee it will work. A standard-conforming C++ compiler could compile it into code that returns 0, crashes, or that initiates Global Thermonuclear War! Which is also true of the code you're presumably already using elsewhere in the library if you need -fno-strict-aliasing for it to behave as intended.
You can try the Diagnostic pragmas and change the level in error for your warnings. More details here:
http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
If your library is a header-only library, I think the only way to deal with this is to fix the strict aliasing violations. If the violations occur between types you define, you can use the usual tricks involving unions, or the may_alias type attribute. If your library uses the predefined sockaddr types, this could be difficult.

What are the differences between g++ version 4.0.0.8 and 4.3.2?

What's the difference between g++ 4.0.0.8 and g++ 4.3.2? These two are the most common C++ compilers that I have seen used in various programming competitions.
I tried to google it, but found nothing.
It's really not such a 'huge list', considering you're interested in the C++ changes between the two.
4.0.0.8 is just a patch revision of 4.0, whose release notes are here: http://gcc.gnu.org/gcc-4.0/changes.html
4.3.2 is a patch revision of 4.3, whose release notes are here: http://gcc.gnu.org/gcc-4.3/changes.html
If you look at the differences between them, I think the following list covers the most important differences between GCC 4.0 and 4.3 that you would really care about.
GCC 4.3.2 has (including changes from GCC 4.1 and GCC 4.2):
Experimental support for the ISO C++0x standard (that's a link)
long long is now officially supported in C++ (though it was an extension provided in older GCC anyway)
Template extern is supported
Right angle brackets like you'd see in std::vector<std::vector<int>> are now supported (note the lack of a space between the two > at the end of the declaration).
experimental support for Variadic Template Arguments
Static assertions
and some others
More TR1 library support
<regex> (gcc 4.3), <random> (gcc 4.2), and <complex> (gcc 4.2)
C++ visibility handling has been overhauled. (GCC 4.2)
Restricted visiblity is propagated from classes to members, from functions to local statics, and from templates and template arguments to instantiations, unless the latter has explicitly declared visibility.
The visibility attribute for a class must come between the class-key and the name, not after the closing brace.
Attributes are now allowed for enums and elaborated-type-specifiers that only declare a type.
Members of the anonymous namespace are now local to a particular translation unit, along with any other declarations which use them, though they are still treated as having external linkage for language semantics.
An undocumented template extension was removed in GCC 4.2 (was deprecated in 4.1)
The (undocumented) extension which permitted templates with default arguments to be bound to template template parameters with fewer parameters has been removed. For example:
template <template <typename> class C>
void f(C<double>) {}
template <typename T, typename U = int>
struct S {};
template void f(S<double>);
is no longer accepted by G++. The reason this code is not accepted is that S is a template with two parameters; therefore, it cannot be bound to C which has only one parameter.
Additionally, check the porting to GCC 4.3 guide, where some important stuff is, like:
Backward compatible/deprecated headers have been removed.
Mostly this means a bunch of pre-standard headers have been removed, like <iostream.h> (use the standard <iostream>), <hash_map.h> (use <tr1/unordered_map>) <hashtable.h> (use <tr1/unordered_map> or <tr1/unordered_set> depending on needs), etc. Again, not a big deal.
Stricter enforcement of standards
For example, the signature on main's two-argument form must be correct.
No duplicate function parameter names
void func(int x, int x); // now an error
And there have been various bug fixes, as well as changes I don't think really affect how you'd write competition code (like removal/addition of new compiler flags), and removal of stuff like the <? and >? operators (ever used those?).
All in all I don't think the differences between the two will cause you much grief if you had to write code for both compilers.
You are wondering about the difference between two different version of g++? It's two common version of GNU C++ compilers. Different Linux releases may have different version of g++ shipped with it. Like my current CentOS 5.5 has g++ 4.1.2 with it.
For you feature details, check the link in you comments.
Since the 4.3.2 is newer then 4.0.0.8, it is more standard compliant. For details, you have to check documentation and release changes