C++ 模板用户定义转换为抽象类引用和英特尔编译器
我有以下(非常简化的)“容器”类: 有时,我需要存储从某个抽象类型派生的对象,并对该抽象类型的引用执行相同类型的转换,例如:C++ 模板用户定义转换为抽象类引用和英特尔编译器,c++,icc,C++,Icc,我有以下(非常简化的)“容器”类: 有时,我需要存储从某个抽象类型派生的对象,并对该抽象类型的引用执行相同类型的转换,例如: boost::shared_ptr<some_abstract_type> x(new some_derived_type); container cx = x; ... // user-defined conversion const some_abstract_type &y = cx; // a template conversion us
boost::shared_ptr<some_abstract_type> x(new some_derived_type);
container cx = x;
...
// user-defined conversion
const some_abstract_type &y = cx;
// a template conversion using a "getter"
const some_abstract_type &y = cx.get<some_abstract_type>();
另一方面,如果我将main()
和foo()
中的base
替换为derived
(或者使用“getter”而不是foo()
中的类型转换),英特尔也可以正常工作。当T
是抽象类时,是否有可能说服英特尔编译器使用用户定义的类型转换为引用类型
提前谢谢你的建议
编辑:有趣的是,使用指针类型的类型转换可以很好地工作。如果我加上
template<typename T>
operator T const * () const
{
return &get<T>();
}
然后它也适用于英特尔。我会在getter中返回一个指针:
template<typename T>
T const * get() const {
return boost::any_cast< boost::shared_ptr<T> >(m_content);
}
< > >强> >:<强> >您的问题的添加正好在这个方向上。 < P> OK,所以它似乎是英特尔C++编译器中的一个bug,并被提交到bug跟踪列表中。我对“代码> ** Boost的推理感到困惑::YANYAXCAST < BooS::SyrdYPPTR>(和MY内容)
>over*boost::any_cast(m_content)
(或者为什么m_content
一开始不仅仅是一个boost::shared_ptr>
,但我猜失去它的原因是因为你的简化);从源代码来看,any_cast
似乎确实支持any
对象的按引用传递(请参见)。@JAB实际上有两个any_cast
的变体,一个是对any
进行(常量/非常量)引用并返回T
(因此创建了一个临时变量),一个函数,它获取指向any
的指针,并返回指向T
的指针(随后可用于从函数返回对T
的引用,因为它不会创建T
的临时实例)。在您引用的情况下,T
在技术上是共享的,当您立即取消对共享指针的引用时,除了尝试节省一点点空间/CPU周期外,您没有理由创建额外的指针。(大多数编译器无论如何都会删除副本,因为共享的\u ptr
确实是在该位置临时使用的,不是吗?除非你发现你使用的编译器在这种情况下不执行删除,否则使用指针形式似乎是一种不必要的先发制人优化。)@JAB我明白了,它实际上也很有效。谢谢编辑了这个问题。愚弄揭示了ICC转换为非常量参考。牺牲了一点常量的正确性,你可能有一个可行的解决办法。谢谢你的评论。这就是为什么我提到这个类是“非常简化的”:-)然而,我在这里不明白的是,这就是我的问题(可能有些隐藏)的要点,为什么英特尔编译器没有“看到”当T
为抽象类型时,用户定义的类型转换为引用类型,而指针类型(抽象/非抽象)的转换不是这种情况。由于我希望避免任何类型的非标准构造,问题可能是我是否做错了什么,或者英特尔编译器中存在错误。我在您的代码中没有看到错误。然而,有时标准的一致性结构并不是每个编译器都支持的。。。
#include <iostream>
#include <boost/any.hpp>
#include <boost/shared_ptr.hpp>
class container
{
public:
template<typename T> container(const boost::shared_ptr<T> &rhs)
: m_content(rhs) { }
template<typename T>
operator T const & () const
{
return get<T>();
}
template<typename T>
T const & get() const
{
return *boost::any_cast< boost::shared_ptr<T> >(m_content);
}
private:
boost::any m_content;
};
class base
{
public:
virtual ~base() { }
virtual void f() const = 0;
};
class derived : public base
{
public:
virtual ~derived() { }
virtual void f() const { std::cout << "hello\n"; }
};
void foo(const container &c)
{
const base & a = c;
a.f();
}
int main()
{
boost::shared_ptr<base> a(new derived);
container c = a;
foo(c);
}
test.cpp(44): error: no suitable user-defined conversion from "const container" to "const base" exists
const base & a = c;
^
compilation aborted for test.cpp (code 2)
template<typename T>
operator T const * () const
{
return &get<T>();
}
void foo(const container &c)
{
const base * a = c;
a->f();
}
template<typename T>
T const * get() const {
return boost::any_cast< boost::shared_ptr<T> >(m_content);
}
void foo(const container &c)
{
const base* a = c.get<base>();
a->f();
}
bool valid() const {
return m_content != NULL;
}