Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to match the int type to a C++ concept requiring a self-defined function?

I’m tyring out the 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 fail 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 the to_string for int is defined out of the scope where the int itself is defined, the compiler fails to recognize that function when trying to fit int in Printable. I wonder if there’s no way to make int Printable.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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";
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading