For the following code snippet (using C++14 standard), can we declare setDataVectoras noexcept?
class Data {
public:
using Type = ...; // A class with a default move assignment operator. Or even just uint32_t
void setDataVector(std::vector<Type> &&input) // Can be declared as noexcept?
{
data = std::move(input);
}
private:
std::vector<Type> data;
};
In cppreference, it is mentioned that until C++17, the move assignment operator for std::vector is not noexcept.
vector& operator=( vector&& other );
Can it really throw even for trivial datatypes like integer?
What is confusing me is that move operations should be exception-safe but std::vector and std::string for example don't have a noexcept move assignment operators.
So, What am I missing here?
Related
When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable which is a requirement for an object/struct to be atomic. Am I just not understanding how to do this correctly, or is this a problem in the c++ standard?
Take the example below:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
Trying to compile this with g++ gives error: use of deleted function 'A<int>::A(const A<int>&)' myA.store(a, std::memory_order_relaxed);. My understanding of this error is that the atomic::store method is looking for that constructor in my struct A but not finding it.
Now here is what happens when I add that constructor:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
A(const A<T>& obj) { }
A( ) { }
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
I no longer receive the above compiler error but a new one coming from the requirements of the atomic class required from 'class B<int>' .... error: static assertion failed: std::atomic requires a trivially copyable type ... In other words by adding the used-defined constructors I have made my struct A a non-trivially copyable object which cannot be initialized in class B. However, without the user-defined constructors I cannot use the store method in myA.store(a, std::memory_order_relaxed).
This seems like a flaw in the design of the std::atomic class. Now maybe I am just doing something wrong because I don't have a lot of experience using C++11 and up (I'm old school). Since 11 there have been a lot of changes and the requirements seem to be a lot stricter. I'm hoping someone can tell me how to achieve what I want to achieve.
Also I cannot change std::atomic<A<T>> myA; to std::atomic<A<T>> * myA; (changed to pointer) or std::atomic<A<T>*> myA;. I realize this will compile but it will destroy the fundamental design of a class I am trying to build.
The problem here resides in the fact that std::atomic requires a trivially copiable type. This because trivially copyable types are the only sure types in C++ which can be directly copied by copying their memory contents directly (eg. through std::memcpy). Also non-formerly trivially copyable types could be safe to raw copy but no assumption can be made on this.
This is indeed important for std::atomic since copy on temporary values is made through std::memcpy, see some implementation details for Clang for example.
Now at the same time std::atomic is not copy constructible, and this is for reasonable reasons, check this answer for example, so it's implicitly not trivially copyable (nor any type which contains them).
If, absurdly, you would allow a std::atomic to contain another std::atomic, and the implementation of std::atomic contains a lock, how would you manage copying it atomically? How should it work?
The following code will not compile on gcc 4.8.2.
The problem is that this code will attempt to copy construct an std::pair<int, A> which can't happen due to struct A missing copy and move constructors.
Is gcc failing here or am I missing something?
#include <map>
struct A
{
int bla;
A(int blub):bla(blub){}
A(A&&) = delete;
A(const A&) = delete;
A& operator=(A&&) = delete;
A& operator=(const A&) = delete;
};
int main()
{
std::map<int, A> map;
map.emplace(1, 2); // doesn't work
map.emplace(std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple(2)
); // works like a charm
return 0;
}
As far as I can tell, the issue isn't caused by map::emplace, but by pair's constructors:
#include <map>
struct A
{
A(int) {}
A(A&&) = delete;
A(A const&) = delete;
};
int main()
{
std::pair<int, A> x(1, 4); // error
}
This code example doesn't compile, neither with coliru's g++4.8.1 nor with clang++3.5, which are both using libstdc++, as far as I can tell.
The issue is rooted in the fact that although we can construct
A t(4);
that is, std::is_constructible<A, int>::value == true, we cannot implicitly convert an int to an A [conv]/3
An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed,
for some invented temporary variable t.
Note the copy-initialization (the =). This creates a temporary A and initializes t from this temporary, [dcl.init]/17. This initialization from a temporary tries to call the deleted move ctor of A, which makes the conversion ill-formed.
As we cannot convert from an int to an A, the constructor of pair that one would expect to be called is rejected by SFINAE. This behaviour is surprising, N4387 - Improving pair and tuple analyses and tries to improve the situation, by making the constructor explicit instead of rejecting it. N4387 has been voted into C++1z at the Lenexa meeting.
The following describes the C++11 rules.
The constructor I had expected to be called is described in [pairs.pair]/7-9
template<class U, class V> constexpr pair(U&& x, V&& y);
7 Requires: is_constructible<first_type, U&&>::value is true and
is_constructible<second_type, V&&>::value is true.
8 Effects: The
constructor initializes first with std::forward<U>(x) and second with
std::forward<V>(y).
9 Remarks: If U is not implicitly convertible to
first_type or V is not implicitly convertible to second_type this
constructor shall not participate in overload resolution.
Note the difference between is_constructible in the Requires section, and "is not implicitly convertible" in the Remarks section. The requirements are fulfilled to call this constructor, but it may not participate in overload resolution (= has to be rejected via SFINAE).
Therefore, overload resolution needs to select a "worse match", namely one whose second parameter is a A const&. A temporary is created from the int argument and bound to this reference, and the reference is used to initialize the pair data member (.second). The initialization tries to call the deleted copy ctor of A, and the construction of the pair is ill-formed.
libstdc++ has (as an extension) some nonstandard ctors. In the latest doxygen (and in 4.8.2), the constructor of pair that I had expected to be called (being surprised by the rules required by the Standard) is:
template<class _U1, class _U2,
class = typename enable_if<__and_<is_convertible<_U1, _T1>,
is_convertible<_U2, _T2>
>::value
>::type>
constexpr pair(_U1&& __x, _U2&& __y)
: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
and the one that is actually called is the non-standard:
// DR 811.
template<class _U1,
class = typename enable_if<is_convertible<_U1, _T1>::value>::type>
constexpr pair(_U1&& __x, const _T2& __y)
: first(std::forward<_U1>(__x)), second(__y) { }
The program is ill-formed according to the Standard, it is not merely rejected by this non-standard ctor.
As a final remark, here's the specification of is_constructible and is_convertible.
is_constructible [meta.rel]/4
Given the following function prototype:
template <class T>
typename add_rvalue_reference<T>::type create();
the predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied if and only if the following variable definition would be well-formed for some invented variable t:
T t(create<Args>()...);
[Note: These tokens are never interpreted as a function declaration. — end note] Access checking is performed as if in a context unrelated to T and any of the Args. Only the validity of the immediate context of the variable initialization is considered.
is_convertible [meta.unary.prop]/6:
Given the following function prototype:
template <class T>
typename add_rvalue_reference<T>::type create();
the predicate condition for a template specialization is_convertible<From, To> shall be satisfied if and
only if the return expression in the following code would be well-formed, including any implicit conversions
to the return type of the function:
To test() {
return create<From>();
}
[Note: This requirement gives well defined results for reference types, void types, array types, and function types. — end note] Access checking is performed as if in a context unrelated to To and From. Only
the validity of the immediate context of the expression of the return-statement (including conversions to
the return type) is considered.
For your type A,
A t(create<int>());
is well-formed; however
A test() {
return create<int>();
}
creates a temporary of type A and tries to move that into the return-value (copy-initialization). That selects the deleted ctor A(A&&) and is therefore ill-formed.
I am unable to understand the use & purpose of the noexcept keyword in C++11/14. I understand that it is a signature for a function that does not emit exceptions. But does it really work?
Look at this code below :
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void seev (vector<int> &v) noexcept;
void seev (vector<int> &v) noexcept
{
for (int i=0;i<10;++i)
{
cout<<v.at(i)<<' ';
}
}
int main()
{
vector<int> v {1,2,3,4,5};
seev(v);
return 0;
}
The above code will surely throw an out_of_range exception. So the use of noexcept here is useless, or is it?
My queries are :
How does noexcept work?
How is it used?
What throw() wasn't able to do that noexcept could?
A noexcept specification on a function is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions.
The compiler can use this information to enable certain optimizations on non-throwing functions as well as enable the noexcept operator, which can check at compile time if a particular expression is declared to throw any exceptions.
For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept, and copy otherwise (unless the copy constructor is not accessible, but a potentially throwing move constructor is, in which case the strong exception guarantee is waived).
noexcept is an improved version of throw(), which is deprecated in C++11. Unlike throw(), noexcept will not call std::unexpected and may or may not unwind the stack, which potentially allows the compiler to implement noexcept without the runtime overhead of throw().
For more details, please visit below websites
https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
When should I really use noexcept?
Edit: Sample source code to illustrate above points.
// whether foo is declared noexcept depends on if the expression
// T() will throw any exceptions, check in compile time
template <class T>
void foo() noexcept(noexcept(T())) {
}
void bar() noexcept(true) {
}
void baz() noexcept {
throw 42;
} // noexcept is the same as noexcept(true)
int main()
{
foo<int>(); // noexcept(noexcept(int())) => noexcept(true), so this is fine
bar(); // fine
baz(); // compiles, but at runtime this calls std::terminate
}
I'm posting 2 pieces of code to explain your problem:
Code 1:
#include <iostream>
using namespace std;
void foo() noexcept // see the noexcept specifier
{
throw 42;
}
int main()
{
try
{
foo();
}
catch(...)
{
cerr<<"exception caught\n";
}
return 0;
}
Here the output will be :-
terminate called after throwing an instance of 'int'
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
If I remove the noexceptthen:
Code 2:
#include <iostream>
using namespace std;
void foo() // noexcept is eliminated
{
throw 42;
}
int main()
{
try
{
foo();
}
catch(...)
{
cerr<<"exception caught\n";
}
return 0;
}
Output will be :-
exception caught
Because foo was signed as noexcept, hence terminate was called.
Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, and move-assignment operators are all noexcept(true) by default, unless they are required to call a function that is noexcept(false), in which case these functions are noexcept(false).
You can also write lines like:
cout << boolalpha << noexcept(foo); // here noexcept acts as
// an operator instead of a specifier
The above line will check if foo will throw an exception or not. If it would throw then the return value will be true else false.
You can read more about these in this: http://scottmeyers.blogspot.dk/2014/03/declare-functions-noexcept-whenever.html
noexcept indicates that a function is intended not to to throw an exception, a guarantee you as a developer provides, that is not enforced by the compiler. So using it in a situation where your function calls functions that might throw exceptions that you do not catch yourself is bad.
The whole range of throw() specifiers were removed because the exception specifiers were less than optimal in C++, see: Difference between C++03 throw() specifier C++11 noexcept
noexcept has the advantage of not stating which exception is thrown, but rather whether an exception is thrown or not. It accepts a parameter which may be false if you expect the function to throw an exception.
The uses of this, can be in for instance an inherited class structure, where one super class wish to "enforce" to an inherited class, that a specific virtual function is not allowed to throw an exception. Further more the compiler may use the information for optimization.
noexcept is also an operator which can evaluate an expression and return whether or not that expression may thrown an exception or not, as per § 5.3.7.
5.3.7 noexcept operator [expr.unary.noexcept]
1 The noexcept operator determines whether the evaluation of its operand, which is an unevaluated operand
(Clause 5), can throw an exception (15.1).
noexcept-expression:
noexcept ( expression )
2 The result of the noexcept operator is a constant of type bool and is an rvalue.
3 The result of the noexcept operator is false if in a potentially-evaluated context the expression would
contain
— a potentially-evaluated call to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification (15.4), unless the call is a constant
expression (5.19),
— a potentially-evaluated throw-expression (15.1),
— a potentially-evaluated dynamic_cast expression dynamic_cast(v), where T is a reference type, that requires a run-time check (5.2.7), or
— a potentially-evaluated typeid expression (5.2.8) applied to a glvalue expression whose type is a polymorphic class type (10.3).
Otherwise, the result is true.
I can't explain the possible optimizations as well as Scott Meyers: http://aristeia.com/EC++11-14/noexcept%202014-03-31.pdf from his blog post: Declare functions noexcept whenever possible?
The difference between unwinding the call stack and possibly unwinding it has a surprisingly large impact on code generation. In a noexcept function, optimizers need not keep the runtime stack in an unwindable state if an exception would propagate out of the function, nor must they ensure that objects in a noexcept function are destroyed in the inverse order of construction should an exception leave the function. The result is more opportunities for optimization, not only within the body of a noexcept function, but also at sites where the function is called. Such flexibility is present only for noexcept functions. Functions with “throw()” exception specifications lack it, as do functions with no exception specification at all.
I have the boost::variant over set of non-default constructible (and maybe even non-moveable/non-copyable and non-copy/move constructible) classes with essentialy different non-default constructor prototypes, as shown below:
#include <boost/variant.hpp>
#include <string>
#include <list>
struct A { A(int) { ; } };
struct B { B(std::string) { ; } };
struct C { C(int, std::string) { ; } };
using V = boost::variant< A const, B const, C const >;
using L = std::list< V >;
int main()
{
L l;
l.push_back(A(1)); // an extra copy/move operation
l.push_back(B("2")); // an extra copy/move operation
l.push_back(C(3, "3")); // an extra copy/move operation
l.emplace_back(4);
l.emplace_back(std::string("5"));
// l.emplace_back(3, std::string("3")); // error here
return 0;
}
I expect, that std::list::emplace_back allows me to construct-and-insert (in single operation) new objects (of all the A, B, C types) into list, even if they have T & operator = (T const &) = delete;/T & operator = (T &&) = delete; and T(T const &) = delete;/T(T &&) = delete;. But what should I do, if constructor is a non-conversion one? I.e. have more, than one parameter. Or what I should to do if two different variant's underlying types have ambiguous constructor prototypes? In my opinion, this is the defect of implementation of the boost::variant library in the light of the new features of C++11 standard, if any at all can be applyed to solve the problem.
I specifically asked about std::list and boost::variant in superposition, because they are both internally implement the pimpl idiom in some form, as far as I know (say, boost::variant currently designed by means of temporary heap backup approach).
emplace can only call the constructors of the type in question. And boost::variant's constructors only take single objects which are unambiguously convertible to one of the variant's types.
variant doesn't forward parameters arbitrarily to one of its bounded types. It just takes a value. A single value that it will try to convert to one of the bounded types.
So you're going to have to construct an object and then copy that into the variant.
Assuming you can modify your "C" class, you could give it an additional constructor that takes a single tuple argument.
I've got a variant class. It has a pair of constructors:
/// Construct and fill.
template <typename T>
inline
variant (const T& t)
{
YYASSERT (sizeof (T) <= S);
new (buffer.raw) T(t);
}
template <typename T>
inline
variant (T&& t)
{
YYASSERT (sizeof (T) <= S);
new (buffer.raw) T(std::move(t));
}
Now I've called those constructors in this code:
parser::symbol_type
parser::make_IDENTIFIER (const Wide::ParsedFile::Identifier*& v)
{
return symbol_type (token::IDENTIFIER, v);
}
symbol_type takes a variant as it's second argument in this specific constructor, and v is being implicitly converted.
However, MSVC will try to use the rvalue reference constructor instead of using the other constructor, resulting in a compilation error when it attempts to new a reference. Why is that, and how can I make it stop?
You generally should not overload a templated T&& function. You should instead have the single function which forwards:
template <typename T>
inline
variant (T&& t)
{
typedef typename std::remove_reference<T>::type Tr;
YYASSERT (sizeof (Tr) <= S);
new (buffer.raw) Tr(std::forward<T>(t));
}
This has the functionality of your two overloads, while avoiding the problem of picking the wrong one.
I believe (not positive) that these are the two variants in your overload set:
varaint<const Wide::ParsedFile::Identifier*>(const Wide::ParsedFile::Identifier*const&)
varaint<const Wide::ParsedFile::Identifier*&>(const Wide::ParsedFile::Identifier*&)
And the second one wins because it is more specialized than the first (I'm making an educated guess, I'm not 100% positive).
The second template would be a better match, because the const specifiers are in different places in your function and in the first constructor.
In the first overload you will have T being deduced as
const Wide::ParsedFile::Identifier*
And then creating a const reference to that type. That adds an extra const.