1 year ago

#344959

test-img

glades

Template argument deduction fails when passing enum

I'm trying to insert an enum parameter into a constexpr function. I have done this in the past and it always worked... except in this case. This case is only special in that I'm calling a factory function first. But apparently C++ doesn't see through this. What can be done?

Those are my errors:

<source>: In function 'constexpr auto operator+(some_enum)':
<source>:30:28: error: no matching function for call to 'signal<1, state>(std::nullptr_t)'
   30 |     return signal<1, state>(nullptr);
      |            ~~~~~~~~~~~~~~~~^~~~~~~~~
<source>:23:37: note: candidate: 'template<bool set, some_enum S, class ... Ts> constexpr signal_str<sizeof... (Ts)> signal(Ts ...)'
   23 | constexpr signal_str<sizeof...(Ts)> signal(Ts... Args)
      |                                     ^~~~~~
<source>:23:37: note:   template argument deduction/substitution failed:
<source>:30:28: error: 'state' is not a constant expression
   30 |     return signal<1, state>(nullptr);
      |            ~~~~~~~~~~~~~~~~^~~~~~~~~
<source>:30:28: note: in template argument for type 'some_enum'
<source>:28:16: error: invalid return type 'auto' of 'constexpr' function 'constexpr auto operator+(some_enum)'
   28 | constexpr auto operator+(some_enum state)
      |                ^~~~~~~~
Compiler returned: 1

This is my code:

#include <array>
#include <cstdint>
#include <iostream>

typedef void* TaskType_t;

enum some_enum
{
    SOME_STATE = 1,
};

template <size_t N> 
struct signal_str
{
    uint32_t val_;
    std::array<TaskType_t, N> tasks_;
};


template <bool set, some_enum S, typename... Ts>
constexpr signal_str<sizeof...(Ts)> signal(Ts... Args)
{
    return signal_str<sizeof...(Ts)>{S, {Args...}}.val_;
}

constexpr auto operator+(some_enum state)
{
    return signal<1, state>(nullptr);
}

int main()
{
    static_assert(+SOME_STATE);
}

I'm using C++17 on xtensa-gcc 8.2.0 but it's the same with gcc 11 (LIVE DEMO).

EDIT: This problem is different from "Why is const variable necessary for template specialization over constants" because enums are already constants. To showcase this the following DOES actually compile:

#include <array>
#include <cstdint>
#include <iostream>

typedef void* TaskType_t;

enum some_enum
{
    SOME_STATE = 1,
};

template <size_t N> 
struct signal_str
{
    uint32_t val_;
    std::array<TaskType_t, N> tasks_;
};

constexpr auto operator+(some_enum state)
{
    return signal_str<1>{state, nullptr}.val_;
}

int main()
{
    static_assert(+SOME_STATE);
}

DEMO

So the problem IMHO is not the enum..

c++

enums

c++17

template-argument-deduction

0 Answers

Your Answer

Accepted video resources