This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.
kill_dependency unconditionally noexceptSection: 32.5.2 [atomics.syn], 32.5.4 [atomics.order] Status: Open Submitter: Daniel Krügler Opened: 2013-01-19 Last modified: 2025-11-06
Priority: 4
View other active issues in [atomics.syn].
View all other issues in [atomics.syn].
View all issues with Open status.
Discussion:
The "magic" kill_dependency function is a function without any constraints on the template parameter T
and is specified as
template <class T> T kill_dependency(T y) noexcept;-14- Effects: The argument does not carry a dependency to the return value (1.10).
-15- Returns:y.
I wonder whether the unconditional noexcept is really intended here:
Assume we have some type U that has a potentially throwing move
constructor (or it has a potentially throwing copy constructor and no
move constructor), for any "normal" function template with the same
signature and the same effects (modulo the dependency magic) this
would mean that it cannot safely be declared noexcept because of the
return statement being part of the complete function call affected by
noexcept (The by-value function argument is irrelevant in this
context). In other words it seems that a function call such as
struct S {
...
S(const S& r) { if(some condition) throw Something(); }
...
};
int main() {
S s1 = ...;
S s2 = std::kill_dependency(s1);
}
would be required to call std::terminate if the copy constructor of S throws during the return
of std::kill_dependency.
Make the exception-specification a constrained one in regard via std::is_nothrow_move_constructible:
template <class T> T kill_dependency(T y) noexcept(see below);
This is similar to the approach taken for function templates such as std::swap.
Use perfect forwarding (This needs further wording to correct the effects):
template <class T> T&& kill_dependency(T&& y) noexcept;
Impose constraints on the template arguments in regard to throwing exceptions while copying/moving.
Keep the state as it is but possibly add a note about a call of std::terminate in above scenario.
A second problem is that the current wording is not clear whether it is well-defined to call the function with types that are reference types, such as in the following example:
#include <atomic>
int main()
{
int a = 12;
int& b = std::kill_dependency<int&>(a);
}
It is unclear what kind of dependency is killed here. This is presumably a core language problem, but could affect the possible resolutions of the problem.
[2014-11 Urbana]
Recommend using a revised example:
int lookup(class D* p)
{
class E* q = p->a.load(memory_order_consume);
int y = std::kill_dependency(q->y);
}
[2015-02 Cologne]
Handed over to SG1.
[2025-10-20; kill_dependency is deprecated so set to priority 4]
[Kona 2025-11-06; SG1 feedback. Status changed: SG1 → Open]
SG1 recommends to reject LWG2236 because kill_dependency is already deprecated
and we don't want to change its behavior.
Proposed resolution: