Bug 95968 - error: 'args#0' is not a constant expression
Summary: error: 'args#0' is not a constant expression
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.1.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: c++-lambda, diagnostic
Depends on:
Blocks: constexpr lambdas
  Show dependency treegraph
 
Reported: 2020-06-29 15:39 UTC by Zakeria Ali
Modified: 2025-01-07 21:59 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-07-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Zakeria Ali 2020-06-29 15:39:34 UTC
Hi,

command: g++ test_class.cpp -Wall -Wextra -std=c++20
System: Debian 10

The following code is rejected by Gcc 10.1. However, if I replace test_class's constructor with constexpr instead of consteval, it does compile on gcc.

// Example program
#include <tuple>
#include <type_traits>
// #include <concepts>

template<typename T, typename ... Pack>
requires(std::is_floating_point<T>::value)
class test_class
{
public:
    const T first_param;
    const std::tuple <Pack...> pack;

    consteval test_class(T first_param_, Pack... pack_) : first_param(first_param_), 
    pack(pack_...)
    {
    }

    consteval auto test_func()
    {
        //auto p = first_param;
        auto x = std::apply([/*p*/](const auto ... args) {return test_class(1.0, args...);}, pack);
        return x;
    }
};

int main()
{
     constexpr auto var1 = test_class(4.0);
     //constexpr auto var2 = test_class(5.0);
     constexpr auto var3 = test_class(12.0, var1).test_func();
     //static_assert(vart3.first_param == 12, "assert fail");
}
error: ‘args#0’ is not a constant expression
   22 |         auto x = std::apply([/*p*/](const auto ... args) {return test_class(1.0, args...);}, pack);
      |                                                                  ^~~~~~~~~~~~~~~~~~~~~~~~


Live demo:
https://godbolt.org/z/oWWFaP
Comment 1 Andrew Pinski 2021-10-02 06:05:07 UTC
Hmm, clang also rejects this (even with libc++).
Comment 2 Andrew Pinski 2022-01-17 10:52:32 UTC
The following is the reduced testcase:
struct test_class
{
    consteval test_class( double pack_) { }
};

void test_func() 
{
    auto t = [](const auto... args) {return test_class(args...);};
    t(1.0);
}

are lambdas consteval by default? I know they are implicit constexpr but I don't think they are consteval though.
There is still a diagnostic issue where args#0 is used as it should be args... instead and maybe a little more clear why args... is not a constant value expression.

Clang gives:
<source>:8:45: error: call to consteval function 'test_class::test_class' is not a constant expression
    auto t = [](const auto... args) {return test_class(args...);};
                                            ^
<source>:9:6: note: in instantiation of function template specialization 'test_func()::(anonymous class)::operator()<double>' requested here
    t(1.0);
     ^
<source>:8:56: note: function parameter 'args' with unknown value cannot be used in a constant expression
    auto t = [](const auto... args) {return test_class(args...);};
                                                       ^
<source>:8:31: note: declared here
    auto t = [](const auto... args) {return test_class(args...);};
                              ^
Comment 3 Andrew Pinski 2023-01-19 01:26:41 UTC
(In reply to Andrew Pinski from comment #2)
> The following is the reduced testcase:
> struct test_class
> {
>     consteval test_class( double pack_) { }
> };
> 
> void test_func() 
> {
>     auto t = [](const auto... args) {return test_class(args...);};
>     t(1.0);
> }
> 
> are lambdas consteval by default? I know they are implicit constexpr but I
> don't think they are consteval though.

They are not until C++23 (See PR 107687 for the status on that).

This is just a diagnostic issue. add constevalue like this to the reduced testcase allows the testcase to work:
    auto t = [](const auto... args) consteval {return test_class(args...);};

Note the original testcase still has issues even if you add consteval to the lambda and I suspect because std::apply still has issues ...