Art*_*kov 2 c++ templates type-conversion
我在模板扣除/类型转换方面遇到问题.以下代码无法编译:
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;
};
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
GCC错误:
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);
^
Run Code Online (Sandbox Code Playgroud)
注释代码(当转换是手动完成时)不会发生问题,如果i_a不是模板类也不会发生.我想知道为什么编译器不能进行转换,如果(根据错误信息)它已经推断出模板类型(这样它应该等同于注释代码).
有没有我可以做的事情而不改变函数的参数类型(我迫切需要它A<T>)?请注意,shared_ptr类仅用于说明问题,我实际上使用另一个智能指针类,我可以轻松更改(如果需要在那里进行更改).
请注意,如果使用原始指针而不是智能指针,一切都像魅力一样!
这里的问题是in 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)
Run Code Online (Sandbox Code Playgroud)
然后T现在可以推导,但是这个函数将接受任何不是我们想要的共享指针.我们只希望T这是一个A<T>什么的是从它衍生出来的.使用std::enable_if,std::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();
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以传递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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
231 次 |
| 最近记录: |