[英]C++ template to check existence of friend function
I am struggling to get the following code to work.我正在努力使以下代码正常工作。 This prints "No setAttr" which feels unexpected.
这会打印出让人意想不到的“No setAttr”。
Basically I have a method in Parent class which creates and instance of a child class and checks whether given type has a particular method or not.基本上我在 Parent class 中有一个方法,它创建一个子 class 的实例并检查给定类型是否具有特定方法。 This works when I make the method (setAttr()) public but doesn't for friend functions.
当我将方法 (setAttr()) 公开但不适用于友元函数时,此方法有效。
I understand that this may seem a bit strange, working with a bit of legacy code, the use case I am trying to solve it to hide a particular method (setAttr()) once created, this should only be accessible from the base class which will be responsible for generating instances of child classes我知道这可能看起来有点奇怪,使用一些遗留代码,我试图解决它的用例是在创建后隐藏特定方法 (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;
}
There are some mistakes in your code:您的代码中有一些错误:
First, you are checking for a method with no parms, but you want to check for the void setAttr(int x)
.首先,您正在检查一个没有参数的方法,但您想检查
void setAttr(int x)
。 If you want to do check for method with int
, your test must be something like: decltype(std::declval<T>().setAttr(1)
( See additional int parameter here! )如果您想使用
int
检查方法,您的测试必须类似于: decltype(std::declval<T>().setAttr(1)
(请参见此处的其他 int 参数!)
If you do so, we run in a gcc bug.如果您这样做,我们会在 gcc 错误中运行。 It complains about a call to a private function inside template declaration, As SFINAE exactly mean that we don't want to rise an error if we have something wrong in declaration of a template.
它抱怨在模板声明中调用私有 function,因为 SFINAE 的确切含义是,如果我们在模板声明中出现错误,我们不想引发错误。 I believe that is a gcc bug.
我相信这是一个 gcc 错误。 clang compiles without any problem.
clang 编译没有任何问题。
BTW: This bug was already discussed here: Private member access in template substitution and SFINAE and here: https://code-examples.net/en/q/25ea9ff顺便说一句:这里已经讨论了这个错误: 模板替换和 SFINAE 中的私有成员访问,这里: https://code-examples.net/en/q/25ea9ff
And now also as a bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96204现在也作为错误报告: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96204
OK, but the result is still permanently return false
.好的,但结果仍然是永久返回
false
。
Why: We simply checking not in context of the current type, so friend
has no effect!为什么:我们只是在当前类型的上下文中检查不是,所以
friend
没有效果!
Solution: Do the check inside the right context.解决方案:在正确的上下文中进行检查。 Simply put the checking templates in the context of the current class.
只需将检查模板放在当前类的上下文中。
So full code example ( only working with clang as gcc complains about private in template declaration which feels wrong! )所以完整的代码示例(仅与 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.