首页 > 解决方案 > 如何在编译期间输出诊断消息以判断调用了哪个重载函数

问题描述

例如,我有重载函数f(),它们被定义为

    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;
    }

Child 类中的函数f重载了父类中的函数。我们如何在编译期间生成诊断信息,以便我们知道编译器选择了哪个函数c.f(1.0)

请注意,如果我删除 line using MyClass:f;,输出会有所不同,但编译不会出错。

更新:

根据@PW 的回答,有两种方法可以修改现有类以使用模板实例化来输出静态断言,

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;
}

我仍然想知道这是否可以without将类或成员函数修改为模板?

标签: c++compiler-warnings

解决方案


一个简单static_assert(false_condition, "...")的总是会在编译时失败。因此,您需要在编译时发生的事情,并且仍然依赖于其他事情。如果您的MyClassChild是模板,您可以这样做。

您还需要一个依赖表达式,因此您可以使用辅助结构来获取与类型相关的内容。

现在您的代码将如下所示:

#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;
}

根据是否using MyClass<T>::f;被评论,你会得到不同的断言。

如果没有评论,你会得到:

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

如果它被评论,你会得到:

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

你可以在这里看到它。


推荐阅读