c++ - c++:如何删除类型的 cv 限定符以访问类函数?
问题描述
这里有一个例子:
#include <iostream>
template<typename T,
typename ... Args>
void print(T&& t, Args&& ... args)
{
// line where compilation fails when the A::run is called
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
{
t.display(std::forward<Args>(args)...);
}
else
{
std::cout << "not applicable !" << std::endl;
}
}
template<typename T>
class A
{
public:
A(T&& t):t_(t){}
template <typename... Args>
void run(Args&& ... args)
{
print<T,Args...>(t_,std::forward<Args>(args)...);
}
T t_;
};
template <typename T> A(T&) -> A<T&>;
template <typename T> A(T&&) -> A<T>;
class B
{
public:
B(int value):value_(value){}
void display(int a, int b)
{
std::cout << value_ << " "
<< a << " "
<< b << std::endl;
}
int value_;
};
int main()
{
int v1=10;
int v2=20;
B b1{1};
A a1{b1};
a1.t_.display(v1,v2);
A a2{B(2)};
a2.t_.display(v1,v2);
//a1.run(v1,v2); // (1)
//a2.run(v1,v2); // (2)
//a1.run(v1);
return 0;
}
上面的代码编译并运行良好。但如果最后 3 行(对 的调用run()
)未注释,则会出现以下编译错误:
(1)
main.cpp:7:48: 错误:'display' 不是 'B&' 的成员</p>
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
(2)
main.cpp:27:25: 错误:没有匹配函数调用'print(B&, int&, int&)'</p>
print<T,Args...>(t_,std::forward<Args>(args)...);
笔记 :
template <typename T> A(T&) -> A<T&>;
template <typename T> A(T&&) -> A<T>;
在这里解释:
解决方案
问题(1)和(2)是不同的问题。
问题(1)来自以下事实std::is_invocable_v
template<typename T,
typename ... Args>
void print(T&& t, Args&& ... args)
{
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
// no T but std::decay_t<T> ...............^...........^
而不是T
(可以作为参考)你需要“腐烂”类型
我提议
template <typename T, typename ... Args>
void print (T && t, Args && ... args)
{
using U = std::decay_t<T>;
if constexpr ( std::is_invocable_v<decltype(&U::display), U*, Args...> )
t.display(std::forward<Args>(args)...);
else
std::cout << "not applicable !" << std::endl;
}
问题(2)来自于在以下print()
调用中解释模板参数的事实
template <typename... Args>
void run(Args&& ... args)
{
print<T,Args...>(t_,std::forward<Args>(args)...);
}
你妨碍了正确的模板扣除。
建议:让模板推演,完善转发,工作和调用函数如下
print(t_,std::forward<Args>(args)...);
推荐阅读
- flutter - 如果键具有相同的值,则对数组中字典的值求和
- python - 如何使用按键将字符串插入子进程输出
- go - 如何覆盖默认 DNS
- ruby-on-rails - 为什么这个视图中的对象为零?
- android - 实时计算记录并返回总记录数,然后在小部件中将其显示为文本
- javascript - 使用 javascript 操作 json
- mpi - MPI 术语中的 ScaLAPACK 子例程是否“阻塞”?
- mpdf - :before 和 :after CSS 属性在 MPDF 中不起作用
- java - 如何使 ExampleMatcher 与属性不匹配?
- ios - 在 iOS 13 上拖动时,UICollectionView 单元格捕捉到原始位置