CS Pei
CS Pei

Reputation: 11047

How to ouput diagnostic messages during compiling time to tell which overloaded function was called

For example, I have overloaded functions, f(), they are defined as

    struct Test {
        int i = 1;
        Test(double d) : i (d){}
    };

    struct MyClass {
        int f(double d) {
            cout << "parent\n";
            return d + 3 ; }
    };

    struct Child : public MyClass {
        using MyClass::f; // if we comment out this line, the output will be different
        double f(Test t) {
            cout << "child\n";
            return t.i * 9;
        }
    };

    int main() {
        Child c;
        std:: cout << c.f(1.0) << std::endl;
    }

The function f in Child class overloaded the function in parent. How can we generate diagnostic information during compiling time, such that we know which function is chosen by the compiler for c.f(1.0)?

Note that if I remove the line using MyClass:f;, the output will be different but there are no error for compiling.

Update:

Based on @P.W 's answer, there are two ways to modify the existing class to use template instantiation to output the static assertion,

template <typename T>
struct ConditionalFalse {
    static constexpr bool value = false;
};

struct Test {
    int i = 1;
    Test(double d) : i (d){}
};
struct MyClass {
    template<typename T>
    int f(double i) {
        static_assert(ConditionalFalse<T>::value, "Parent");
        return i + 3 ; }
};

struct Child : public MyClass {
    using MyClass::f;
    template<typename T>
    double f(Test t) {
        static_assert(ConditionalFalse<T>::value, "Child");
        return t.i * 9;
    }
};

template<typename T>
struct MyClassT {
    int f(double i) {
        static_assert(ConditionalFalse<T>::value, "ParentT");
        return i + 3 ; }
};

template<typename T>
struct ChildT : public MyClassT<T> {
    using MyClassT<T>::f;
    double f(Test t) {
        static_assert(ConditionalFalse<T>::value, "ChildT");
        return t.i * 9;
    }
};

int main() {
    Child c;
    std:: cout << c.f<int>(1.0) << std::endl;

    ChildT<int> ct;
    std:: cout << ct.f(1.0) << std::endl;
}

I am still wondering if this is possible without modifying the class or the member function to be a template?

Upvotes: 0

Views: 58

Answers (1)

P.W
P.W

Reputation: 26800

A simple static_assert(false_condition, "...") would fail at compile time always. So you need something that happens at compile-time and is still dependent on something else. You can do this if your MyClass and Child were templates.

You will also need a dependent expression, and so you can use a helper struct to get something that will be type-dependent.

Now your code will look like this:

#include<iostream>

template <typename T>
struct ConditionalFalse { static constexpr bool value = false; };

struct Test {
    int i = 1;
    Test(double d) : i (d){}
};

template <typename T>
struct MyClass {
    int f(double d) {
        static_assert(ConditionalFalse<T>::value, "The Parent function is called\n");        
        return d + 3 ; }
};

template <typename T>
struct Child : public MyClass<T> {
    using MyClass<T>::f; // if we comment out this line, the output will be different
    double f(Test t) {
    static_assert(ConditionalFalse<T>::value, "The Child function is called\n");        
        return t.i * 9;
    }
};

int main() {
    Child<int> c; //The template parameter doesn't matter

    std::cout << c.f(1.0) << std::endl;
}

Depending on whether using MyClass<T>::f; is commented or not you will get different assertions.

If it is not commented, you will get:

error: static assertion failed: The Parent function is called
         static_assert(ConditionalFalse<T>::value, "The Parent function is called\n");
                       ^~~~~~~~~~~~~~~~~~~

If it is commented, you will get:

<source>:22:19: error: static assertion failed: The Child function is called
     static_assert(ConditionalFalse<T>::value, "The Child function is called\n");
                   ^~~~~~~~~~~~~~~~~~~

You can see it live here.

Upvotes: 2

Related Questions