Search code examples
c++templatesc++20

Trouble with Template Matching Function Overloads in C++20


I'm currently working on a C++20 project where I need to implement a series of overloaded functions using template matching. I am trying to create a set of function templates that can distinguish between different categories of types (e.g., integral types, floating-point types, and custom classes) and handle each with a specialized algorithm.

However, I'm running into an issue where the compiler is not selecting the most specialized template overload as I expected. I've simplified my code to illustrate the problem:

#include <iostream>
#include <type_traits>

// Overload for integral types
template<typename T>
requires std::is_integral_v<T>
void process(T value) {
    std::cout << "Integral: " << value << std::endl;
}

// Overload for floating-point types
template<typename T>
requires std::is_floating_point_v<T>
void process(T value) {
    std::cout << "Floating-point: " << value << std::endl;
}

// Overload for custom class
class MyCustomClass {};

template<>
void process<MyCustomClass>(MyCustomClass value) {
    std::cout << "MyCustomClass instance" << std::endl;
}

int main() {
    process(10);        // Should call the integral overload
    process(3.14);      // Should call the floating-point overload
    process(MyCustomClass()); // Should call the custom class overload
}

When I compile this code with g++ (GCC) 10.2.0, I receive an error that suggests the compiler is unable to deduce the correct overload:

error: template-id ‘process’ for ‘void process(MyCustomClass)’ does not match any template declaration’

I'm looking for guidance on the following points:

  1. Why is the compiler not selecting the correct overload for MyCustomClass?
  2. Is there a better way to structure my function templates for such type-based overloading in C++20?
  3. Could the issue be related to the concepts I'm using, or is it a problem with my function template specializations?

I've checked CPPReference and other Stack Overflow questions but haven't found a solution that resolves my issue. I'm compiling with the -std=c++20 flag.


Solution

  • The problem is that you don't have a primary template in your code to explicitly specialize!

    This means that to resolve the error, you can either provide a primary template or change the explicit specialization to a non-template overload.

    Method 1

    Here we provide a primary template as shown below:

    //added this primary template
    template<typename T>
    void process(T);
    
    //other code as before
    

    Working demo


    Method 2

    Second way is to just provide an ordinary non-template overload instead of an explicit specialization:

    //note the template<> has been removed from here
    void process(MyCustomClass value) {
        std::cout << "MyCustomClass instance" << std::endl;
    }
    

    Working demo