See <https://wg21.link/P2738R1>.
Confirmed.
Reduced version of the paper's testcase that we already (wrongly) accept: class Doer { private: const void *ob; int (*fn)(const void *); public: template <typename T> constexpr Doer(const T &t) : ob{&t}, fn{[](const void *p) { return static_cast<const T *>(p)->doit(); }} {} constexpr int operator()() const { return fn(ob); } }; struct Thing { constexpr int doit() const { return 42; }; }; static_assert (Doer(Thing())() == 42);
Version of the paper testcase that just adds constexpr, that we currently reject: #include <string_view> struct Sheep { constexpr std::string_view speak() const noexcept { return "Baaaaaa"; } }; struct Cow { constexpr std::string_view speak() const noexcept { return "Mooo"; } }; class Animal_View { private: const void *animal; std::string_view (*speak_function)(const void *); public: template <typename Animal> constexpr Animal_View(const Animal &a) : animal{&a}, speak_function{[](const void *object) { return static_cast<const Animal *>(object)->speak(); }} {} constexpr std::string_view speak() const noexcept { return speak_function(animal); } }; // This is the key bit here. This is a single concrete function // that can take anything that happens to have the "Animal_View" // interface constexpr std::string_view do_speak(Animal_View av) { return av.speak(); } int main() { // A Cow is a cow. The only think that makes it special // is that it has a "std::string_view speak() const" member constexpr Cow cow; constexpr auto result = do_speak(cow); return static_cast<int>(result.size()); }
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:a1c6e9631ca33990a2b7411060ca4d18db081a7d commit r14-2146-ga1c6e9631ca33990a2b7411060ca4d18db081a7d Author: Jason Merrill <jason@redhat.com> Date: Sat Jun 24 05:15:02 2023 -0400 c++: C++26 constexpr cast from void* [PR110344] P2768 allows static_cast from void* to ob* in constant evaluation if the pointer does in fact point to an object of the appropriate type. cxx_fold_indirect_ref already does the work of finding such an object if it happens to be a subobject rather than the outermost object at that address, as in constexpr-voidptr2.C. P2768 PR c++/110344 gcc/c-family/ChangeLog: * c-cppbuiltin.cc (c_cpp_builtins): Update __cpp_constexpr. gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression): In C++26, allow cast from void* to the type of a pointed-to object. gcc/testsuite/ChangeLog: * g++.dg/cpp26/constexpr-voidptr1.C: New test. * g++.dg/cpp26/constexpr-voidptr2.C: New test. * g++.dg/cpp26/feat-cxx26.C: New test.
Implemented for GCC 14.
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>: https://gcc.gnu.org/g:8d344146727da02eb5c62fbf6cee97a4e96d63db commit r14-2535-g8d344146727da02eb5c62fbf6cee97a4e96d63db Author: Jason Merrill <jason@redhat.com> Date: Fri Jul 14 09:37:21 2023 -0400 c++: c++26 regression fixes Apparently I wasn't actually running the testsuite in C++26 mode like I thought I was, so there were some failures I wasn't seeing. The constexpr hunk fixes regressions with the P2738 implementation; we still need to use the old handling for casting from void pointers to heap variables. PR c++/110344 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_constant_expression): Move P2738 handling after heap handling. * name-lookup.cc (get_cxx_dialect_name): Add C++26. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/constexpr-cast2.C: Adjust for P2738. * g++.dg/ipa/devirt-45.C: Handle -fimplicit-constexpr.