Home > front end >  how to specify C callable concept when the callable parameters types are deduced
how to specify C callable concept when the callable parameters types are deduced

Time:02-03

I invoke a templated lambda from a templated function, the lambda parameters type are deduced. If the type of the lambda if auto, it works : https://godbolt.org/z/WYxj5G8vx

#include <iostream>
#include <cstdint>
#include <array>
#include <functional>
#include <numeric>
#include <concepts>


template <typename T>
int testf2(T, auto fun) {
  std::array<std::uint8_t, sizeof(T)> ar{};
  std::iota(ar.begin(), ar.end(), 0);
  return fun(ar);
}


int main() { 
    auto f2 = []<size_t S> (std::array<uint8_t, S> arr) -> int  {
       return arr[S -1];
   };

   std::cout << "R = " << testf2(5, f2) << std::endl;
}

I wanted to use std::invocable concept to specialize the auto fun parameter of testf2, to be anything but a callable that take std::array<std::uint8_t, N> as parameter.

Using gcc11.2 or clang13, when I try

template <typename T, size_t S>
int testf2(T, std::invocable<std::array<uint8_t, S>> auto fun) {
  std::array<std::uint8_t, sizeof(T)> ar{};
  std::iota(ar.begin(), ar.end(), 0);
  return fun(ar);
}

I get error :

candidate template ignored: couldn't infer template argument 'S' int testf2(T, std::invocable<std::array<uint8_t, S>> auto fun) {

I don't understand why the compiler can infer type when only auto is used, but not with a constraining concept.

What is the correct way to use concept in this situation ?

This is a simplified version of the code, in reality the signature of testf2 is testf2(auto fun, ARGS... args) and the size of the array is calculated upon the parameter pack types.

CodePudding user response:

Concepts (and requires clauses in general) do not participate in template argument deduction. Since your S in this case is just sizeof(T), you should use that.

the size S is the sum of all the sizes of the types of a parameter pack

Then make it sizeof(Args) ....

CodePudding user response:

This is a simplified version of the code, in reality the signature of testf2 is testf2(auto fun, ARGS... args) and the size of the array is calculated upon the parameter pack types.

Why not just calculate the actual value of S as the size parameter of the std::array?

#include <concepts>

template <typename... ARGS>
int testf2(
  std::invocable<std::array<uint8_t, (sizeof(ARGS)   ...   0)>> auto fun, 
  ARGS... args);

Demo

  •  Tags:  
  • Related