Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to match the int type to a C++ concept requiring a valid function?

I'm trying out templates and concepts in C++. I wrote the following code.

#include <iostream>
#include <string>

template <typename T>
concept Printable = requires(T a) {
    { to_string(a) } -> std::same_as<std::string>;
};

typedef struct myStruct {
    std::string name;
} myStruct_t;

// Implement to_string for myStruct_t
std::string to_string(myStruct_t arg) {
    return arg.name;
}

// Implement to_string for int
std::string to_string(int arg) {
    return "it's an integer";
}

// a function that requires Printable
template <typename T>
requires Printable<T>
void show(T arg) {
    std::cout << to_string(arg) << std::endl;
}

int main(){
    myStruct_t a = {"hello"};
    show(a); // passes compilation
    show(5); // error: no matching function for call to ‘show(int)’
             // note: the required expression ‘to_string(a)’ is invalid
    return 0;
}

The compiler successfully recognizes that myStruct_t satisfies Printable concept but fails to match int with Printable concept. I wonder how I can inform the compiler that the int is also Printable.

I've searched the internet and found that the compiler finds the to_string function needed for Printable concept through argument-dependent lookup(ADL). Since int is not subject to ADL, the compiler fails to recognize the function when trying to check int in Printable. I wonder if there's no way to make int Printable.

like image 632
Lipid L Avatar asked Oct 21 '25 23:10

Lipid L


1 Answers

Using gcc and -fconcepts-diagnostics-depth=2 we see:

<source>:216:21:   in requirements with 'T a' [with T = int]
<source>:217:16: note: the required expression 'to_string(a)' is invalid, because
  217 |     { to_string(a) } -> std::same_as<std::string>;
      |       ~~~~~~~~~^~~
<source>:217:16: error: 'to_string' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation
<source>:230:13: note: 'std::string to_string(int)' declared here, later in the translation unit
  230 | std::string to_string(int arg) {
      |             ^~~~~~~~~

This means, that the concept is not satisfied for int, because at the point of the concept definition the function to_string(int) was not declared yet.

I wonder if there's no way to make int Printable

You can either move the implementation of to_string(int) above the concept or add a forward declaration there.

// forward-declare to_string for int
std::string to_string(int arg);

template <typename T>
concept Printable = requires(T a) {
    { to_string(a) } -> std::same_as<std::string>;
};

// [...]

// Implement to_string for int
std::string to_string(int arg) {
    return "it's an integer";
}
like image 95
perivesta Avatar answered Oct 23 '25 15:10

perivesta



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!