https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94260

            Bug ID: 94260
           Summary: Specific friend function inside c++20
                    concept-constrained class template triggers 'not
                    usable in a constant expression' error
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: niekb at scintilla dot utwente.nl
  Target Milestone: ---

Dear GCC-devs,

I stumbled upon the following error, while working with a particular friend
function inside a concepts-contrained templated class. I tried to make a
minimal example, but maybe it can be further slimmed down.

I am not sure if this is a bug in GCC; however, on clang-trunk the same code
compiles with no error. 

I've created examples on Godbolt's Compiler Explorer. The example on which
GCC-trunk fails is:
https://godbolt.org/z/fc3HbB

The same code compiles successfully with Clang-trunk:
https://godbolt.org/z/JiB_UB

The error disappears when removing the concept-constraint from the class
definition.
The error also disappears when turning the 'fun' function into an non-friend
function.


kind regards,
Niek


NB: I've also copy-pasted the source code below:


#include <utility>
#include <concepts>
#include <future>

template<typename T>
concept my_concept = std::regular<T>;

template <typename T, typename runtime_t> 
class wrapper
{
 T d;
 runtime_t& x;
public:
 wrapper(T&& data, runtime_t& runtime) : 
    d(std::move(data)),
    x(runtime) {}
T& fut()
{
    return d;
}
runtime_t& runtime()
{
    return x;
}
};


template<my_concept field_element>
//template<typename field_element>  // replacing the above line by this line
fixes the compilation error on GGC-trunk
class test {
public:
    friend auto fun(wrapper<std::shared_future<field_element>,
test<field_element>>& a,
                        wrapper<std::shared_future<field_element>,
test<field_element>>& b)
        -> wrapper<std::shared_future<field_element>, test<field_element>>
    {
        return wrapper<std::shared_future<field_element>, test<field_element>>
(   
            std::async(std::launch::deferred, [a,b]() mutable { return
a.fut().get() + b.fut().get(); }),
            a.runtime() 
            );
    }
};

int main(){
    static_assert(std::regular<int>);

    test<int> t;
    std::shared_future<int> f1 = std::async(std::launch::deferred, []() {
return 42; });
    std::shared_future<int> f2 = std::async(std::launch::deferred, []() {
return 42; });

    wrapper<std::shared_future<int>, test<int>> a(std::move(f1),t); 
    wrapper<std::shared_future<int>, test<int>> b(std::move(f2),t); 

    fun(a, b);

}

Reply via email to