gpt4 book ai didi

c++ - 模板推导/类型转换错误

转载 作者:搜寻专家 更新时间:2023-10-30 23:52:56 24 4
gpt4 key购买 nike

我在模板推导/类型转换方面遇到了问题。以下代码编译失败:

template <typename Type>
struct A
{
void DoA()
{
}
};

struct B : public A<B>
{
void DoB()
{
}
};

template <typename T>
void DoSmth(const std::shared_ptr<A<T>> &p)
{
p->DoA();
}

int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<B> pb(new B);
DoSmth(pb);

//std::shared_ptr<A<B>> pa(pb);
//DoSmth(pa);
return 0;
};

MSVC错误如下:

error C2664: 'void DoSmth<B>(const std::shared_ptr<A<B>> &)' : cannot convert argument 1 from 'std::shared_ptr<B>' to 'const std::shared_ptr<A<B>> &'
Binding to reference with added qualification
followed by
Call to constructor 'std::shared_ptr<A<B>>::shared_ptr<B,void>(const std::shared_ptr<B> &) throw()'
c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(531) : see declaration of 'std::shared_ptr<A<B>>::shared_ptr'
followed by
Binding to reference

海湾合作委员会错误:

prog.cpp:28:11: error: no matching function for call to ‘DoSmth(std::shared_ptr<B>&)’
DoSmth(pb);
^
prog.cpp:21:6: note: candidate: template<class T> void DoSmth(const std::shared_ptr<A<T> >&)
void DoSmth(const std::shared_ptr<A<T>> &p)
^~~~~~
prog.cpp:21:6: note: template argument deduction/substitution failed:
prog.cpp:28:11: note: mismatched types ‘A<T>’ and ‘B’
DoSmth(pb);
^

问题不会发生在注释代码中(当手动完成转换时),如果 i_a 也不会发生。不是模板类。我想知道如果(根据错误消息)编译器已经推断出模板类型(这样它应该等同于注释代码),为什么编译器不能进行转换。

在不更改函数参数类型的情况下,我可以做些什么吗(我迫切需要它是 A<T> )?请注意 shared_ptr class 只是用来说明问题,我实际上使用了另一个智能指针类,我可以轻松更改它(以防需要在那里进行更改)。

另请注意,如果使用原始指针而不是智能指针,一切都会像魅力一样!

最佳答案

这里的问题是 void DoSmth(const std::shared_ptr<A<T>> &p) T是依赖类型,不能推导。所以我们需要给编译器一些帮助。幸运的是我们可以使用 SFINAE std::is_base_of 来约束模板。如果我们使用

template <typename T>
void DoSmth(const std::shared_ptr<T> &p)

然后 T现在可以推导了,但是这个函数将接受任何不是我们想要的共享指针。我们只想要一个 T那是一个A<T>或从中派生的东西。使用 std::enable_ifstd::is_base_of我们可以这样做

template <typename T, typename = typename std::enable_if<std::is_base_of<A<T>, T>::value>::type>
void DoSmth(const std::shared_ptr<T> &p)
{
p->DoA();
}

现在我们可以传递 std::shared_ptr<B>到功能而无需做任何额外的事情。这是一个显示它工作的例子,它也拒绝了 shared_ptr非派生类型:

#include <type_traits>
#include <memory>

template <typename Type>
struct A
{
void DoA()
{
}
};

struct B : public A<B>
{
void DoB()
{
}
};

struct Foo {};

template <typename T, typename = typename std::enable_if<std::is_base_of<A<T>, T>::value>::type>
void DoSmth(const std::shared_ptr<T> &p)
{
p->DoA();
}

int main()
{
std::shared_ptr<B> pb(new B);
DoSmth(pb); // this compiles
std::shared_ptr<Foo> pf(new Foo);
DoSmth(pf); // this will generate a compiler error

//std::shared_ptr<A<B>> pa(pb);
//DoSmth(pa);
return 0;
}

Live Example

关于c++ - 模板推导/类型转换错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42808514/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com