3

In the following snippet I try to convert a lambda to my own function object, constraining it with a concept based on the invocable_r type trait. Yet gcc rejects it.

Demo

#include <concepts>
#include <cstdio>


template <typename Fn, typename R, typename... Args>
concept invocable_r = std::is_invocable_r<R, Fn, Args...>::value;

template <typename R, typename... Args>
class function
{
    template <invocable_r<R, Args...> Cb>
    function(Cb fn) {
        printf("Converting constructor invoked!\n");
    }

};

int main()
{
    function<void()> hello = [](){};
}

Error:

error: conversion from 'main()::<lambda()>' to non-scalar type 'function<void()>' requested

I can't seem to find the issue. What's wrong?

glades
  • 3,778
  • 1
  • 12
  • 34

1 Answers1

3

You defined template of function wrong. Your version accepts multiple arguments, when infarct you wish to have one argument of specific type.

You need to use template specialization. Also you have forgotten about public::

#include <concepts>
#include <cstdio>


template <typename Fn, typename R, typename... Args>
concept invocable_r = std::is_invocable_r<R, Fn, Args...>::value;

template <typename T>
class function;

template <typename R, typename... Args>
class function<R(Args...)>
{
public:
    template <invocable_r<R, Args...> Cb>
    function(Cb fn) {
        printf("Copy constructor invoked!\n");
    }

};

int main()
{
    function<void()> hello = [](){};
}

https://godbolt.org/z/xrvr3sMj3

Your version must be used this way:

int main()
{
    function<void> hello = [](){};
}

https://godbolt.org/z/xvGd1s4az

BTW there is std::invocable concept, so you have introduced something what is already covered by std.

Marek R
  • 32,568
  • 6
  • 55
  • 140
  • You're of course right. Interesting that you actually _need_ template specialization in this case – glades Dec 12 '22 at 14:40
  • I wonder if this can be done with concepts only? Probably own concept is needed which will have template specialization anyway. IMO this is shortcoming of std concept library. – Marek R Dec 12 '22 at 14:46
  • I _did_ in fact use a concept, check above ^^. Yes it's a shortcoming of the concepts library. Also, I had to switch around template parameters to make it fit – glades Dec 12 '22 at 14:47