如何 dynamic_cast 参数中带有不匹配引用修饰符的可变参数模板?
How to dynamic_cast a variadic template with mismatch reference modifier in parameters?
我有一个 class 层次结构,其中基础 class 包含一个函数,该函数根据它的参数测试 dynamic_cast
this
指向派生模板类型的指针收到。
问题是 dynamic_cast
运算符会检查参数是否完全匹配,同时考虑它们是否为 ref。我需要以下示例来处理这两种情况,有没有办法做到这一点?
template <typename... P>
struct Derived;
struct Base
{
virtual ~Base() {}
template <typename... P>
void doCast(P&&... p) {
Derived<P...> *res=dynamic_cast<Derived<P...> *>(this);
if (!res)
std::cout<<"Failed."<<std::endl;
else {
std::cout<<"Success."<<std::endl;
res->doSomethingWithP(std::forward<P>(p)...);
}
}
};
template <typename... P>
struct Derived: public Base
{
void doSomethingWithP(P... p) {
/*Whatever, doesn't matter*/
}
};
int main(int argc, char **argv)
{
Derived<int, int, int> derived;
Base *b=&derived;
int x=10;
int y=20;
int z=30;
//The two calls must succeed.
b->doCast(x,y,z); //Failed.
b->doCast(10,20,30); //Success.
return 0;
}
Derived
可以接受既是值、引用又是指针的类型 - cv 限定与否。
只是将我的评论移至答案。在典型情况下,如果 Derived<int>
和 Derived<int const&>
都被允许作为类型,则 Base::doCast
可能必须为每个参数类型执行两次不同的转换,或者 2^N
总转换。这是不可行的。
但是,您可以做的是 (1) 要求 Derived
的模板参数不是引用,以及 (2) 通过引用获取其参数。所以我们只删除所有 P
s:
的引用
template <typename... P>
void doCast(P&&... p) {
if (auto res = dynamic_cast<Derived<std::remove_reference_t<P>...>*>(this)) {
std::cout << "Success." << std::endl;
res->doSomethingWithP(p...); // NOT forward
}
else {
std::cout << "Failed." << std::endl;
}
}
并在另一边引用,这样我们就不会招致额外的副本:
template <typename... P>
struct Derived: public Base
{
void doSomethingWithP(P&... ) {
/*Whatever, doesn't matter*/
}
};
但是,这仍然让我们可以Derived<int&>
,永远不会在此模型中工作。因此,让我们明确禁止这样做。首先是一些样板:
template<bool...> struct bool_pack;
template<bool f, bool... bs>
using all_same = std::is_same<bool_pack<bs..., f>, bool_pack<f, bs...>>;
template <bool... bs>
using none = all_same<false, bs...>;
然后:
template <typename... P>
struct Derived: public Base
{
static_assert(none<std::is_reference<P>::value...>::value,
"Can't make Derived with references");
...
};
我有一个 class 层次结构,其中基础 class 包含一个函数,该函数根据它的参数测试 dynamic_cast
this
指向派生模板类型的指针收到。
问题是 dynamic_cast
运算符会检查参数是否完全匹配,同时考虑它们是否为 ref。我需要以下示例来处理这两种情况,有没有办法做到这一点?
template <typename... P>
struct Derived;
struct Base
{
virtual ~Base() {}
template <typename... P>
void doCast(P&&... p) {
Derived<P...> *res=dynamic_cast<Derived<P...> *>(this);
if (!res)
std::cout<<"Failed."<<std::endl;
else {
std::cout<<"Success."<<std::endl;
res->doSomethingWithP(std::forward<P>(p)...);
}
}
};
template <typename... P>
struct Derived: public Base
{
void doSomethingWithP(P... p) {
/*Whatever, doesn't matter*/
}
};
int main(int argc, char **argv)
{
Derived<int, int, int> derived;
Base *b=&derived;
int x=10;
int y=20;
int z=30;
//The two calls must succeed.
b->doCast(x,y,z); //Failed.
b->doCast(10,20,30); //Success.
return 0;
}
Derived
可以接受既是值、引用又是指针的类型 - cv 限定与否。
只是将我的评论移至答案。在典型情况下,如果 Derived<int>
和 Derived<int const&>
都被允许作为类型,则 Base::doCast
可能必须为每个参数类型执行两次不同的转换,或者 2^N
总转换。这是不可行的。
但是,您可以做的是 (1) 要求 Derived
的模板参数不是引用,以及 (2) 通过引用获取其参数。所以我们只删除所有 P
s:
template <typename... P>
void doCast(P&&... p) {
if (auto res = dynamic_cast<Derived<std::remove_reference_t<P>...>*>(this)) {
std::cout << "Success." << std::endl;
res->doSomethingWithP(p...); // NOT forward
}
else {
std::cout << "Failed." << std::endl;
}
}
并在另一边引用,这样我们就不会招致额外的副本:
template <typename... P>
struct Derived: public Base
{
void doSomethingWithP(P&... ) {
/*Whatever, doesn't matter*/
}
};
但是,这仍然让我们可以Derived<int&>
,永远不会在此模型中工作。因此,让我们明确禁止这样做。首先是一些样板:
template<bool...> struct bool_pack;
template<bool f, bool... bs>
using all_same = std::is_same<bool_pack<bs..., f>, bool_pack<f, bs...>>;
template <bool... bs>
using none = all_same<false, bs...>;
然后:
template <typename... P>
struct Derived: public Base
{
static_assert(none<std::is_reference<P>::value...>::value,
"Can't make Derived with references");
...
};