#include <tuple> struct F final { }; std::tuple<F> t; This should work. I don't know how to make it work without a compiler-assisted is_final trait.
I'll have a go at implementing __is_final, using Paolo's work for PR 26099 as a starting point.
Yes, should be pretty trivial given the infrastructure already in place. In semantics should be just matter of calling CLASS_TYPE_P && CLASSTYPE_FINAL
Created attachment 25961 [details] front end patch (missing docs and tests)
Created attachment 25962 [details] library patch (missing tests)
Thanks for the pointer, the hardest part was naming the new intrinsic ;) We can't have the front-end define __is_final() as an intrinsic and also define std::__is_final as a class template, so the patches above define __is_final_class() and std::__is_final<> It might be better for the front end to define __is_final() then use that directly in the library and not provide a type trait unless std::is_final gets added to the library by a DR. i.e. in <tuple> template<typename _Tp> using __empty_base = typename conditional<__is_final(_Tp), false_type, is_empty<_Tp>>::type;
Created attachment 25963 [details] fix other parts of library here's a proof of concept patch showing how to fix existing code that inherits from allocators so that it is ABI-compatible for non-final allocators and also supports final allocators (by inheriting from a wrapper class instead). Something like this needs to be done for the containers so they stay backwards compatible but also work with final types. (I decided to rename the intrinsic to __is_final and that's what this patch uses)
Here's another testcase: #include <future> #include <memory> template<typename T> struct final_allocator final : std::allocator<T> { final_allocator() = default; template<typename U> final_allocator(const final_allocator<U>&) { } template<typename U> struct rebind { typedef final_allocator<U> other; }; }; final_allocator<int> a; std::promise<int> p(std::allocator_arg, a);
patch implementing __is_final submitted for approval: http://gcc.gnu.org/ml/gcc-patches/2011-12/msg00231.html
Hello, the recent discussion "Structure alignment changes when a constructor or destructor is added" on gcc-help made me wonder whether it would make sense to not only derive for empty classes, but actually derive by default and use members only when necessary (builtin types, final classes). The advantage would be that derivation allows for a slightly more compact representation in some cases with the g++ ABI. I really haven't thought much about the consequences. Sorry for hijacking this bug with this wild idea, but in case it makes sense it might change slightly the way you want to fix it.
I haven't really thought about it either, but one advantage of depending on is_empty is that it prevents using the EBO for polymorphic classes, where derivation could have undesirable effects. That *shouldn't* be a problem as long as user-defined types don't have virtual functions using reserved names such as _M_get. Another problem could be user-defined types with a virtual base, if the tuple node type (which would be the most-derived type) doesn't know how to construct the virtual base. struct A { A(int) { } }; struct B : virtual A { B() : A(1) { } }; std::tuple<B> t; If tuple derived from B it couldn't construct the A subobject correctly.
(In reply to comment #10) > I haven't really thought about it either, but one advantage of depending on > is_empty is that it prevents using the EBO for polymorphic classes, where > derivation could have undesirable effects. Ah, right, the set of types that can safely be derived from is rather restricted: non-builtin, non-final, non-virtual (and possibly more constraints). And to benefit from additional packing: non-C++03-POD. Probably not worth the trouble...
Author: redi Date: Thu Dec 15 10:02:45 2011 New Revision: 182360 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=182360 Log: c-family: PR libstdc++/51365 * c-common.c (RID_IS_FINAL): Add. * c-common.h (RID_IS_FINAL): Add. cp: PR libstdc++/51365 * cp-tree.h (CPTK_IS_FINAL): Add. * parser.c (cp_parser_translation_unit): Handle RID_IS_FINAL. (cp_parser_primary_expression, cp_parser_trait_expr): Likewise. * semantics.c (trait_expr_value, finish_trait_expr): Handle CPTK_IS_FINAL. * cxx-pretty-print.c (pp_cxx_trait_expression): Likewise. testsuite: PR libstdc++/51365 * g++.dg/ext/is_final.C: New. Added: trunk/gcc/testsuite/g++.dg/ext/is_final.C Modified: trunk/gcc/c-family/ChangeLog trunk/gcc/c-family/c-common.c trunk/gcc/c-family/c-common.h trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/cxx-pretty-print.c trunk/gcc/cp/parser.c trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog
front end changes done, I'll work on the library parts this weekend
Author: redi Date: Tue Dec 20 09:09:50 2011 New Revision: 182523 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=182523 Log: PR libstdc++/51365 * include/std/tuple (_Tuple_impl): Check __is_final as well as is_empty. * testsuite/20_util/tuple/51365.cc: New. Added: trunk/libstdc++-v3/testsuite/20_util/tuple/51365.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/std/tuple
Given the number of other PRs I'm working on and that we're in stage4 I'm not going to handle 'final' allocators for 4.7 so I'll come back to it for 4.8 (when I also plan to update all the containers to use C++11 allocators)
GCC 4.8.0 is being released, adjusting target milestone.
shared_ptr fixed to handle final allocators by: Author: redi Date: Sun Apr 28 11:38:21 2013 New Revision: 198367 URL: http://gcc.gnu.org/viewcvs?rev=198367&root=gcc&view=rev Log: PR libstdc++/51365 * include/bits/shared_ptr_base (_Sp_ebo_helper): Helper class to implement EBO safely. (_Sp_counted_base::_M_get_deleter): Add noexcept. (_Sp_counter_ptr): Use noexcept instead of comments. (_Sp_counted_deleter): Likewise. Use _Sp_ebo_helper. (_Sp_counted_ptr_inplace): Likewise. * testsuite/20_util/shared_ptr/cons/51365.cc: New. * testsuite/20_util/shared_ptr/cons/52924.cc: Add rebind member to custom allocator and test construction with custom allocator. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error line number. Added: trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/51365.cc - copied, changed from r198365, trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/52924.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/bits/shared_ptr_base.h trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc trunk/libstdc++-v3/testsuite/20_util/shared_ptr/cons/52924.cc
GCC 4.9.0 has been released
I'm closing this as fixed, I've created Bug 60921 to deal with the remaining final allocator issues.