On OS X, simple C++ program gives incorrect results (which are a result of command-line options 'c++03' vs 'c++11')
Firstly, the expected difference in behaviour is because the operator<<(std::ostream&, const char*)
overload (it's actually a function template specialization, but nevermind for now) has a parameter of type std::ostream&
and an lvalue reference can only bind to an lvalue, and in your example the stream is an rvalue so that overload can't be used. In C++03 that means the only viable overload is the std::ostream::operator<<(const void*)
member function, because member functions can be called on rvalue objects, so the string is written out as a void*
address in hexadecimal. In C++11 there is a new operator<<(std::ostream&&, const T&)
function template that allows writing to rvalue streams, and forwards to the operator<<(std::ostream&, const char*)
overload, so the string is output rather than a hex address.
On GNU/Linux you are presumably using a fairly recent GCC release, which has fairly good support for C++11 in both the compiler (g++) and the standard library (libstdc++) so it has the operator<<(std::ostream&&, const T&)
overload and everything Just Works.
On OS X you are probably using Clang with GCC's standard library, libstdc++. Xcode ships with an ancient version of GCC by default (4.2) and the standard library from GCC 4.2 doesn't support C++11, so doesn't have the operator<<
overload for rvalue streams. Using -std=c++0x
tells Clang to support C++11 language features (such as rvalue references), but doesn't magically make GCC 4.2's library grow C++11 code that wasn't even a twinkle in the standard committee's eye when GCC 4.2 was released. Rather than shipping a non-prehistoric libstdc++ Apple instead wrote their own standard library implementation to go with LLVM and Clang projects. Using -stdlib=libc++
tells clang to use that libc++ standard library implementation instead of the ancient libstdc++. As libc++ was written recently it has the operator<<
overload for rvalue references.
c++ -std=c++11 -stdlib=libc++ giving errors on osx lion
The Solution
Specifically, I had to go to XCode preferences->Downloads and install "Command Line Tools". That fixed the problem.
The Explanation
What happened was a simple case of outdated software. Since OSX was up-to-date (through software update), I assumed all the XCode and compiler updates are also in place. Which was not the case.
Notice in the comment to the question I said "I have the latest version of XCode for Lion." But I didn't.(bames53 alludes to that in his answer) Just because you don't have any new updates in the OSX software update doesn't mean that you have the latest XCode compiler. You update it through XCode Preferences.
With the help of Jonathan's feedback and some more googling, Using clang with libc++ and c++11 from the command line with mac os x fixed my problem.
This actually updated the llvm toolchain.
$ c++ --version
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.4.2
Thread model: posix
How do I execute a command and get the output of the command within C++ using POSIX?
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
Pre-C++11 version:
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>
std::string exec(const char* cmd) {
char buffer[128];
std::string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe) throw std::runtime_error("popen() failed!");
try {
while (fgets(buffer, sizeof buffer, pipe) != NULL) {
result += buffer;
}
} catch (...) {
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
Replace popen
and pclose
with _popen
and _pclose
for Windows.
What is a bus error? Is it different from a segmentation fault?
Bus errors are rare nowadays on x86 and occur when your processor cannot even attempt the memory access requested, typically:
- using a processor instruction with an address that does not satisfy its alignment requirements.
Segmentation faults occur when accessing memory which does not belong to your process. They are very common and are typically the result of:
- using a pointer to something that was deallocated.
- using an uninitialized hence bogus pointer.
- using a null pointer.
- overflowing a buffer.
PS: To be more precise, it is not manipulating the pointer itself that will cause issues. It's accessing the memory it points to (dereferencing).
How do I fix maven error The JAVA_HOME environment variable is not defined correctly?
The SETX
command does not modify the current environment.
If you run the following batch file:
setx AAA aaa
echo AAA=%AAA%
It will print
AAA=
So your batch file is wrong. You have to use set
:
set AAA=aaa
See What is the difference between SETX and SET in environment variables in Windows.
Asking the user for input until they give a valid response
The simplest way to accomplish this is to put the input
method in a while loop. Use continue
when you get bad input, and break
out of the loop when you're satisfied.
When Your Input Might Raise an Exception
Use try
and except
to detect when the user enters data that can't be parsed.
while True:
try:
# Note: Python 2.x users should use raw_input, the equivalent of 3.x's input
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
#better try again... Return to the start of the loop
continue
else:
#age was successfully parsed!
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Implementing Your Own Validation Rules
If you want to reject values that Python can successfully parse, you can add your own validation logic.
while True:
data = input("Please enter a loud message (must be all caps): ")
if not data.isupper():
print("Sorry, your response was not loud enough.")
continue
else:
#we're happy with the value given.
#we're ready to exit the loop.
break
while True:
data = input("Pick an answer from A to D:")
if data.lower() not in ('a', 'b', 'c', 'd'):
print("Not an appropriate choice.")
else:
break
Combining Exception Handling and Custom Validation
Both of the above techniques can be combined into one loop.
while True:
try:
age = int(input("Please enter your age: "))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if age < 0:
print("Sorry, your response must not be negative.")
continue
else:
#age was successfully parsed, and we're happy with its value.
#we're ready to exit the loop.
break
if age >= 18:
print("You are able to vote in the United States!")
else:
print("You are not able to vote in the United States.")
Encapsulating it All in a Function
If you need to ask your user for a lot of different values, it might be useful to put this code in a function, so you don't have to retype it every time.
def get_non_negative_int(prompt):
while True:
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
continue
if value < 0:
print("Sorry, your response must not be negative.")
continue
else:
break
return value
age = get_non_negative_int("Please enter your age: ")
kids = get_non_negative_int("Please enter the number of children you have: ")
salary = get_non_negative_int("Please enter your yearly earnings, in dollars: ")
Putting It All Together
You can extend this idea to make a very generic input function:
def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None):
if min_ is not None and max_ is not None and max_ < min_:
raise ValueError("min_ must be less than or equal to max_.")
while True:
ui = input(prompt)
if type_ is not None:
try:
ui = type_(ui)
except ValueError:
print("Input type must be {0}.".format(type_.__name__))
continue
if max_ is not None and ui > max_:
print("Input must be less than or equal to {0}.".format(max_))
elif min_ is not None and ui < min_:
print("Input must be greater than or equal to {0}.".format(min_))
elif range_ is not None and ui not in range_:
if isinstance(range_, range):
template = "Input must be between {0.start} and {0.stop}."
print(template.format(range_))
else:
template = "Input must be {0}."
if len(range_) == 1:
print(template.format(*range_))
else:
expected = " or ".join((
", ".join(str(x) for x in range_[:-1]),
str(range_[-1])
))
print(template.format(expected))
else:
return ui
With usage such as:
age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))
Common Pitfalls, and Why you Should Avoid Them
The Redundant Use of Redundant input
Statements
This method works but is generally considered poor style:
data = input("Please enter a loud message (must be all caps): ")
while not data.isupper():
print("Sorry, your response was not loud enough.")
data = input("Please enter a loud message (must be all caps): ")
It might look attractive initially because it's shorter than the while True
method, but it violates the Don't Repeat Yourself principle of software development. This increases the likelihood of bugs in your system. What if you want to backport to 2.7 by changing input
to raw_input
, but accidentally change only the first input
above? It's a SyntaxError
just waiting to happen.
Recursion Will Blow Your Stack
If you've just learned about recursion, you might be tempted to use it in get_non_negative_int
so you can dispose of the while loop.
def get_non_negative_int(prompt):
try:
value = int(input(prompt))
except ValueError:
print("Sorry, I didn't understand that.")
return get_non_negative_int(prompt)
if value < 0:
print("Sorry, your response must not be negative.")
return get_non_negative_int(prompt)
else:
return value
This appears to work fine most of the time, but if the user enters invalid data enough times, the script will terminate with a RuntimeError: maximum recursion depth exceeded
. You may think "no fool would make 1000 mistakes in a row", but you're underestimating the ingenuity of fools!
c++11: clang refuses numeric_limits in my template definition, while gcc accepts it - which is right?
Your code compiles just fine with clang++ 3.2, see here.
I would say there is nothing wrong with your code but you should upgrade to a newer version of clang.
Note: The code doesn't compile with the Intel C++ Compiler 13.0.1 due to a compiler bug (thanks @Xeo):
Compilation finished with errors:
source.cpp(6): internal error: assertion failed: ensure_il_scope_exists: NULL IL scope (shared/cfe/edgcpfe/il.c, line 7439)
size_t MAX_SIZE = std::numeric_limits<size_t>::max()>
^
compilation aborted for source.cpp (code 4)
Related Topics
Correct Way to Define C++ Namespace Methods in .Cpp File
Branch Prediction on a Function Pointer
Why C++11 Compiler Support Still Requires a Flag
Why Can't I Assign an Array Variable Directly to Another Array Variable with the '=' Operator
How to Print the Address of Char Array
G++ Linker: Force Static Linking If Static Library Exists
How to Initialize 'Std::Function' with a Member-Function
How to Simulate Printf's %P Format When Using Std::Cout
Elegant Way to Implement Extensible Factories in C++
Comparison of Arrays in Google Test
Protected Data in Parent Class Not Available in Child Class
What Is the Meaning of This Star (*) Symbol in C++? - Pointer to Member
In C++ Why Can't I Write a For() Loop Like This: For( Int I = 1, Double I2 = 0;
Why Do I Get a Template Error If I Name My Function 'Swap', But 'Swap' Is Okay
Partially Truncating a Stream (Fstream or Ofstream) in C++