Currently I am trying to work with the std::filesystem. I'm working on Windows 7 64-bit using MinGW-W64 GCC 7.1.0. Since this compiler does not support the std::filesystem, I have to include the experimental version and link with -lstdc++fs.
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
This worked fine up to the point where I wanted to create nested directories. If I create the directories one at a time using create_directory(), everything works perfect. Now if I use create_directories() instead, it throws a filesystem_error if one of the directories already exists.
fs::path levelA{"."};
fs::path levelB{"folder"};
fs::path levelAB = levelA / levelB; // "./folder"
bool create_separately; // set this bool as needed
if (create_separately) {
/* This works perfectly */
fs::create_directory(levelA);
fs::create_directory(levelAB);
}
else {
/* This throws because "." already exists */
fs::create_directories(levelAB);
}
Comparing the documentation of the experimental version to the standard version, an additional sentence was added for the standard version:
Executes (1) for every element of p that does not already exist. If p already exists, the function does nothing (this condition is not treated as an error).
Why was this treated as an error in the first place? Is this considered a bug?
Additionaly, is there an easy way to update GCC on Windows? I read something about GCC 8.1.0 being released and some new MinGW version supporting it, but I can't seem to find any downloads.
Maybe you meant this, but note that only the second sentence you quoted is changed relative to the TS version—and has changed again since this question was asked. It refers to the case where p already exists and might not be a directory; the function returns false to indicate that it did nothing, but at the time of asking it didn’t report any error, regardless of the nature of p. The logic was that most operating systems do not distinguish this situation, so it was left to the application developer to ask, if they care.
It was added as a result of an LWG issue; the meaning of the previous wording was unclear at best, with no explanation of what happened if the function failed to satisfy its stated postcondition. There is no general notion of “postcondition failure is an error”, but rather that “postcondition failure in the absence of a reported error is logically impossible”.
Since the initial version of this answer, a paper was accepted that changed it to be an error if and only if the conflicting object is not a directory, requiring a subsequent check on many platforms. This is unusual for C++, but the result was thought to be more intuitive and the operation is relatively expensive anyway.
Regardless, the reason your implementation fails on . would seem to be that it’s buggy. (I don’t have any special hints about how to most easily obtain a newer version.)
Related
Reading this blog post and its comments, I have noticed that it gives as an example the possibility of marking specific function parameters as deprecated, as in (exaple taken from the post):
// Deprecate a function parameter
int triple([[deprecated]] int x);
Now I was wondering, what is a good use case for such a feature? No one in the comments of that post or anywhere else I have searched seem to have a clue.
EDIT:
To see it in action, there is a compilable example on goldbolt
Say you had a function like this:
void* allocate(std::size_t sz, void* hint = nullptr) {
// if you give `hint` it *might* be more efficient
}
And then you decided that it is no longer worth the effort to do stuff based on hint. So you would do this:
void* allocate(std::size_t sz, [[deprecated]] void* hint = nullptr) {
// `hint` is ignored. The compiler warns me if I use it in the
// function body accidentally, and people reading the function
// signature can see that it is probably going to be ignored.
}
This allows the library to keep the same signature/ABI (So you don't need to recompile stuff that uses it and legacy code can still keep using it without doing any harm), and also prevents it from accidentally being used again when changing the function.
But this is mostly for developers of the function, not the users of the function, in the future so they know why a seemingly "useless" parameter is there.
I would also think that this would disable the "unused parameter" warning with the -Werror=unused-parameter flag in gcc/clang, but it doesn't. Using (void) deprecated_parameter also issues a warning about using a deprecated parameter, so this seems like a bug. If it did disable the unused param warning, that would be another use case for [[deprecated]].
The rule is that the attribute is valid on, amongst other things, variable declarations (broadly). It's not specifically permitted for such declarations found in function arguments.
The original proposal, N3394, doesn't mention such a use case, either, and neither does the documentation for the original feature in GCC (which regardless accepts the equivalent usage) or in VS (I didn't check Clang).
As such, I think it's an "accident" that this is permitted, not something that anyone really had in mind as being useful.
Could it be useful to document deprecated defaulted arguments, as Artyer explores? Yes, potentially, and vaguely. But as Artyer also found, mainstream compilers don't actually react to this usage in a helpful manner.
So, at the present time, it's not useful, and the language feature wasn't particularly designed to be useful in this case.
Imagine a library that is implemented, used and maintained for many years. This library is used in multiple projects.
If you would simply remove the parameter, all the projects would have to immediately adapt the source code to be able to compile again, after they upgraded to the new library version.
If a default value is added to the parameter, but the parameter not used anymore, the projects would still compile without any change, but nobody would note that something has changed at all, and maybe some behaviour/feature that was controlled by this parameter does not work anymore.
So, by marking the parameter as deprecated the projects can compile without a change, but they get a warning that something has changed and that they should change their source code, because sooner or later this parameter will disappear.
constexpr permits expressions which can be evaluated at compile time to be ... evaluated at compile time.
Why is this keyword even necessary? Why not permit or require that compilers evaluate all expressions at compile time if possible?
The standard library has an uneven application of constexpr which causes a lot of inconvenience. Making constexpr the "default" would address that and likely improve a huge amount of existing code.
It already is permitted to evaluate side-effect-free computations at compile time, under the as-if rule.
What constexpr does is provide guarantees on what data-flow analysis a compliant compiler is required to do to detect1 compile-time-computable expressions, and also allow the programmer to express that intent so that they get a diagnostic if they accidentally do something that cannot be precomputed.
Making constexpr the default would eliminate that very useful diagnostic ability.
1 In general, requiring "evaluate all expressions at compile time if possible" is a non-starter, because detecting the "if possible" requires solving the Halting Problem, and computer scientists know that this is not possible in the general case. So instead a relaxation is used where the outputs are { "Computable at compile-time", "Not computable at compile-time or couldn't decide" }. And the ability of different compilers to decide would depend on how smart their test was, which would make this feature non-portable. constexpr defines the exact test to use. A smarter compiler can still pre-compute even more expressions than the Standard test dictates, but if they fail the test, they can't be marked constexpr.
Note: despite the below, I admit to liking the idea of making constexpr the default. But you asked why it wasn't already done, so to answer that I will simply elaborate on mattnewport's last comment:
Consider the situation today. You're trying to use some function from the standard library in a context that requires a constant expression. It's not marked as constexpr, so you get a compiler error. This seems dumb, since "clearly" the ONLY thing that needs to change for this to work is to add the word constexpr to the definition.
Now consider life in the alternate universe where we adopt your proposal. Your code now compiles, yay! Next year you decide you to add Windows support to whatever project you're working on. How hard can it be? You'll compile using Visual Studio for your Windows users and keep using gcc for everyone else, right?
But the first time you try to compile on Windows, you get a bunch of compiler errors: this function can't be used in a constant expression context. You look at the code of the function in question, and compare it to the version that ships with gcc. It turns out that they are slightly different, and that the version that ships with gcc meets the technical requirements for constexpr by sheer accident, and likewise the one that ships with Visual Studio does not meet those requirements, again by sheer accident. Now what?
No problem you say, I'll submit a bug report to Microsoft: this function should be fixed. They close your bug report: the standard never says this function must be usable in a constant expression, so we can implement however we want. So you submit a bug report to the gcc maintainers: why didn't you warn me I was using non-portable code? And they close it too: how were we supposed to know it's not portable? We can't keep track of how everyone else implements the standard library.
Now what? No one did anything really wrong. Not you, not the gcc folks, nor the Visual Studio folks. Yet you still end up with un-portable code and are not a happy camper at this point. All else being equal, a good language standard will try to make this situation as unlikely as possible.
And even though I used an example of different compilers, it could just as well happen when you try to upgrade to a newer version of the same compiler, or even try to compile with different settings. For example: the function contains an assert statement to ensure it's being called with valid arguments. If you compile with assertions disabled, the assertion "disappears" and the function meets the rules for constexpr; if you enable assertions, then it doesn't meet them. (This is less likely these days now that the rules for constexpr are very generous, but was a bigger issue under the C++11 rules. But in principle the point remains even today.)
Lastly we get to the admittedly minor issue of error messages. In today's world, if I try to do something like stick in a cout statement in constexpr function, I get a nice simple error right away. In your world, we would have the same situation that we have with templates, deep stack-traces all the way to the very bottom of the implementation of output streams. Not fatal, but surely annoying.
This is a year and a half late, but I still hope it helps.
As Ben Voigt points out, compilers are already allowed to evaluate anything at compile time under the as-if rule.
What constexpr also does is lay out clear rules for expressions that can be used in places where a compile time constant is required. That means I can write code like this and know it will be portable:
constexpr int square(int x) { return x * x; }
...
int a[square(4)] = {};
...
Without the keyword and clear rules in the standard I'm not sure how you could specify this portably and provide useful diagnostics on things the programmer intended to be constexpr but don't meet the requirements.
So, I have to admit upfront I already know the answer. I'm asking so others who happen to run into the same problem can find a solution to the problem caused by incorrect documentation.
My environment is VS 2015 C++, wxWidgets 3.0.2, developing on Windows 7.
In some legacy code, calls to wxMkDir were not being checked for success. According to wxWidgets documentation, wxMkDir has a return type of bool, and returns true if successful. However, it returns 0 when successful.
Why?
The answer is two-fold: there are two functions with similar names, wxMkdir and wxMkDir, with the former being documented and the latter not documented. The second part is that the seemingly valid presumption that they will behave the same is not a valid assumption.
The undocumented function wxMkDir maps to wxCRT_MkDir, which in turn maps to wxCRT_MkDirA, then to wxPOSIX_IDENT(mkdir), which creates a platform dependent name for the mentioned POSIX function, mkdir. According to the POSIX documentation for mkdir
Upon successful completion, mkdir() shall return 0. Otherwise, -1 shall be returned, no directory shall be created, and errno shall be set to indicate the error.
So, conditionals like:
if (!wxMkDir(newDir)) {
// handle the error here
}
will fail, but:
if (wxMkDir(newDir) != 0) {
// handle the error here
}
will work as anticipated based on whether the directory was created or not.
The documented function wxMkdir is implemented in wx source file filefn.cpp, and utilizes mkdir, but with conditionals like the above to map to the appropriate bool return value.
wxMkdir() and wxMkDir() are the unfortunate and ugly exceptions to the general rule that wxWidgets provides wxFoo() wrapper for all standard (meaning either ANSI C or POSIX as, in practice, the latter is about as standard and more so than C99) functions foo() existing in both narrow (char*) and wide (wchar_t*) versions.
So, according to this general rule, you'd expect wxMkdir() to behave as std::mkdir() but unfortunately wxMkdir() predated, by quite a few years, Unicode-ification of wxWidgets and so this rule couldn't be implemented for it because of backwards compatibility and another function had to be invented to be just a wrapper for std::mkdir().
And by now, of course, the weight of backwards compatibility is even heavier and there really doesn't seem to be anything reasonable to do here -- other than advising people to use wxFileName::Mkdir() which is unambiguous.
</sad-story>
I am using Boost 1.46 with Turtle lib 1.2.4 and compiler from Visual Studio Express 2013. I have following class to MOCK:
struct IPredicate
{
virtual ~IPredicate() {}
virtual bool operator()(float value) = 0;
};
When I mock operator() with MOCK_NON_CONST_METHOD:
MOCK_BASE_CLASS(MockPredicate, IPredicate)
{
MOCK_NON_CONST_METHOD(operator(), 1, bool(float), id)
};
I got bunch of compiler errors, e.g. syntax error 'operator ' and so on. But when I mock it with MOCK_NON_CONST_METHOD_EXT:
MOCK_BASE_CLASS(MockPredicate, IPredicate)
{
MOCK_NON_CONST_METHOD_EXT(operator(), 1, bool(float), id)
};
everything is ok and works perfectly! According to http://turtle.sourceforge.net/turtle/reference.html MOCKS with EXT suffix are for "compilers without support for variadic macros", but the one I am using has support (checked it with these examples: http://msdn.microsoft.com/en-us/library/ms177415.aspx ). The rest of the documentation isn't really clear about this case.
Is anyone able to explain me what's the case here? Why I have the errors when I don't use EXT suffixed MOCK version?
The stickler’s answer would be that generally there are no guarantees with respect to variadic macros, as variadic macros are non-standard in C++03 (but are standard in C++11). So if you have a method which avoids variadic macros you should definitely use it instead the one with the variadic macros.
Practically though it is very likely that the turtle library hasn’t been extensively tested with msc and is simply relying on one of the non-standard gcc extensions for the macros. The extensions are discussed on the Variadic Macros http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html page. Specifically, for the turtle library to be portable for all C99 conformant compilers only __VA_ARGS__ could be used.
With macros, when you are after the root case - use the /P switch for msc (Preprocess to a File) to generate an .i file with the pre-processors directives expanded, where you can check what's it unhappy about.
Update. As I finished spanning this long story, I decided to quickly download the turtle and check how the macro is defined. And as I did, I discovered that this is simply a sad case of unmaintained documentation. Running grep on the library includes I couldn't find MOCK_NON_CONST_METHOD defined at all. That's why you are getting syntax errors. Another reason to avoid macros - clarity and sanity of C++ error messages.
(I'm the author of turtle)
What happened with 1.2.4 is that for a reason I didn't really investigate the code provided is actually 1.2.1 along with the 1.2.4 documentation.
As nobody complained by opening a ticket directly on sourceforge I didn't notice until quite some time had passed (all my personal and company projects using turtle are continuously integrated with the latest source code).
Anyway, I just tested your code and it compiles with MSVC 2013, turtle 1.2.6 and boost 1.55. If you haven't already done so by the time, you should consider upgrading.
The canonical way to read lines from a text file is:
std::fstream fs("/tmp/myfile.txt");
std::string line;
while (std::getline(line, fs)) {
doThingsWith(line);
}
(no, it is not while (!fs.eof()) { getline(line, fs); doThingsWith(line); }!)
This works beacuse std::getline returns the stream argument by reference, and because:
in C++03, streams convert to void*, via an operator void*() const in std::basic_ios, evaluating to the null pointer value when the fail error flag is set;
see [C++03: 27.4.4] & [C++03: 27.4.4.3/1]
in C++11, streams convert to bool, via an explicit operator bool() const in std::basic_ios, evaluating to false when the fail error flag is set
see [C++11: 27.5.5.1] & [C++11: 27.5.5.4/1]
In C++03 this mechanism means the following is possible:
std::cout << std::cout;
It correctly results in some arbitrary pointer value being output to the standard out stream.
However, despite operator void*() const having been removed in C++11, this also compiles and runs for me in GCC 4.7.0 in C++11 mode.
How is this still possible in C++11? Is there some other mechanism at work that I'm unaware of? Or is it simply an implementation "oddity"?
I'm reasonably certain this is not allowed/can't happen in a conforming implementation of C++11.
The problem, of course, is that right now, most implementations are working on conforming, but aren't there completely yet. At a guess, for many vendors, this particular update is a fairly low priority. It improves error checking, but does little (or nothing) to enable new techniques, add new features, improve run-time efficiency, etc. This lets the compiler catch the error you've cited (some_stream << some_other_stream) but doesn't really make a whole lot of difference otherwise.
If I were in charge of updating a standard library for C++11, I think this would be a fairly low priority. There are other changes that are probably as easy (if not easier) to incorporate, and likely to make a much bigger difference to most programmers.
To use one of the examples you gave, if I were in charge of updating the VC++ standard library to take advantage of the compiler features added in the November CTP, my top priority would probably be to add constructors to the standard container types to accept initialization_lists. These are fairly easy to add (I'd guess one person could probably add and test them in under a week) and make quite an obvious, visible difference in what a programmer can do.
As late as GCC 4.6.2, the libstdc++ code for basic_ios is evidently still C++03-like.
I'd simply put this down to "they haven't gotten around to it yet".
By contrast, the libc++ (LLVM's stdlib implementation) trunk already uses operator bool().
This was a missed mini-feature buried in a pre-existing header. There are probably lots of missing error of omission and commission in pre-2011 components.
Really, if anyone comes up with things like this in gcc then it would do a world of good to go to Bugzilla and make a bug report. It may be a low priority bug but if you start a paper trail
I'll go out on a limb and extend this idea to all the other C++ compilers: clang, Visual Studio,etc.
This will make C++ a better place.
P.S. I entered a bug in Bugzilla.