繁体   English   中英

C++ 模板来检查朋友的存在 function

[英]C++ template to check existence of friend function

我正在努力使以下代码正常工作。 这会打印出让人意想不到的“No setAttr”。

基本上我在 Parent class 中有一个方法,它创建一个子 class 的实例并检查给定类型是否具有特定方法。 当我将方法 (setAttr()) 公开但不适用于友元函数时,此方法有效。

我知道这可能看起来有点奇怪,使用一些遗留代码,我试图解决它的用例是在创建后隐藏特定方法 (setAttr()),这应该只能从基础 class 访问将负责生成子类的实例

template <typename, typename = void_t<>>
struct has_set_attr_method {
  static constexpr bool value = false;
};
template <typename T>
struct has_set_attr_method<T, void_t<decltype(std::declval<T>().setAttr())>> {
  static constexpr bool value = true;
};


struct Parent {
public:
    template<typename T>
    static void create()    {
        auto obj = T::create();
        if constexpr(has_set_attr_method<T>::value) {
            cout << "has setAttr" << endl;
            obj.toString();
        } else {
            cout << "no setAttr" << endl;
        }
    }
};

struct Child : public Parent {
public:
friend class Parent;
    static auto create() {
        return Child();
    }

private:
    void setAttr(int x) {
    }
};

int main(int argc, char const *argv[]) {
    Parent::create<Child>();
    return 0;
}

您的代码中有一些错误:

首先,您正在检查一个没有参数的方法,但您想检查void setAttr(int x) 如果您想使用int检查方法,您的测试必须类似于: decltype(std::declval<T>().setAttr(1) (请参见此处的其他 int 参数!)

如果您这样做,我们会在 gcc 错误中运行。 它抱怨在模板声明中调用私有 function,因为 SFINAE 的确切含义是,如果我们在模板声明中出现错误,我们不想引发错误。 我相信这是一个 gcc 错误。 clang 编译没有任何问题。

顺便说一句:这里已经讨论了这个错误: 模板替换和 SFINAE 中的私有成员访问,这里: https://code-examples.net/en/q/25ea9ff

现在也作为错误报告: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96204

好的,但结果仍然是永久返回false

为什么:我们只是在当前类型的上下文中检查不是,所以friend没有效果!

解决方案:在正确的上下文中进行检查。 只需将检查模板放在当前类的上下文中。

所以完整的代码示例(仅与 clang 一起使用,因为 gcc 抱怨模板声明中的 private 感觉不对!)

struct Parent {   
    template <typename, typename = void_t<>>
        struct has_set_attr_method {
            static constexpr bool value = false;
        };
    template <typename T>
        struct has_set_attr_method<T, void_t<decltype(std::declval<T>().setAttr(1))>> {
            static constexpr bool value = true;
        };  

    public:
    template<typename T>
        static void create()    {   
            auto obj = T::create();
            if constexpr(has_set_attr_method<T>::value) {
                cout << "has setAttr" << endl;
            } else {
                cout << "no setAttr" << endl;
            }   
        }   
};  

struct Child : public Parent {
    public:
        //friend class Parent;
        static auto create() {
            return Child();
        }   

    private:
        void setAttr(int x) {
        }
};  

int main(int argc, char const *argv[]) {
    Parent::create<Child>();
    return 0;
}   

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM