简体   繁体   English

使用Visual Studio 2010时出现错误/不正确的C2248错误

[英]Erroneous/Incorrect C2248 error using Visual Studio 2010

I'm seeing what I believe to be an erroneous/incorrect compiler error using the Visual Studio 2010 compiler. 我正在使用Visual Studio 2010编译器看到我认为是错误/不正确的编译器错误。 I'm in the process of up-porting our codebase from Visual Studio 2005 and I ran across a construct that was building correctly before but now generates a C2248 compiler error. 我正在从Visual Studio 2005向上移植我们的代码库,并且我遇到了之前正在构建的构造,但现在生成了C2248编译器错误。

Obviously, the code snippet below has been generic-ized, but it is a compilable example of the scenario. 显然,下面的代码片段已经通用化,但它是该场景的可编辑示例。 The ObjectPtr<T> C++ template comes from our codebase and is the source of the error in question. ObjectPtr<T> C ++模板来自我们的代码库,是有问题的错误的来源。 What appears to be happening is that the compiler is generating a call to the copy constructor for ObjectPtr<T> when it shouldn't (see my comment block in the SomeContainer::Foo() method below). 似乎正在发生的事情是编译器在不应该生成对ObjectPtr<T>的复制构造函数的调用时(参见下面的SomeContainer::Foo()方法中的注释块)。 For this code construct, there is a public cast operator for SomeUsefulData * on ObjectPtr<SomeUsefulData> but it is not being chosen inside the true expression if the ?: operator. 对于此代码构造,在ObjectPtr<SomeUsefulData>上有SomeUsefulData *的公共SomeUsefulData *运算符,但如果是?:运算符,则不在真实表达式中选择它。 Instead, I get the two errors in the block quote below. 相反,我在下面的块引用中得到了两个错误。

Based on my knowledge of C++, this code should compile. 根据我对C ++的了解,这段代码应该编译。 Has anyone else seen this behavior? 有没有人见过这种行为? If not, can someone point me to a clarification of the compiler resolution rules that would explain why it's attempting to generate a copy of the object in this case? 如果没有,有人可以指出我对编译器解析规则的澄清,这可以解释为什么它在这种情况下试图生成对象的副本吗?

Thanks in advance, 提前致谢,
Dylan Bourque 迪伦布尔克

Visual Studio build output: Visual Studio构建输出:

c:\\projects\\objectptrtest\\objectptrtest.cpp(177): error C2248: 'ObjectPtr::ObjectPtr' : cannot access private member declared in class 'ObjectPtr' c:\\ projects \\ objectptrtest \\ objectptrtest.cpp(177):错误C2248:'ObjectPtr :: ObjectPtr':无法访问类'ObjectPtr'中声明的私有成员
with
[ T=SomeUsefulData ] [T = SomeUsefulData]
c:\\projects\\objectptrtest\\objectptrtest.cpp(25) : see declaration of 'ObjectPtr::ObjectPtr' c:\\ projects \\ objectptrtest \\ objectptrtest.cpp(25):参见'ObjectPtr :: ObjectPtr'的声明
with
[ T=SomeUsefulData ] [T = SomeUsefulData]
c:\\projects\\objectptrtest\\objectptrtest.cpp(177): error C2248: 'ObjectPtr::ObjectPtr' : cannot access private member declared in class 'ObjectPtr' c:\\ projects \\ objectptrtest \\ objectptrtest.cpp(177):错误C2248:'ObjectPtr :: ObjectPtr':无法访问类'ObjectPtr'中声明的私有成员
with
[ T=SomeUsefulData ] [T = SomeUsefulData]
c:\\projects\\objectptrtest\\objectptrtest.cpp(25) : see declaration of 'ObjectPtr::ObjectPtr' c:\\ projects \\ objectptrtest \\ objectptrtest.cpp(25):参见'ObjectPtr :: ObjectPtr'的声明
with
[ T=SomeUsefulData ] [T = SomeUsefulData]


Below is a minimal, compilable example of the scenario: 以下是该场景的最小可编辑示例:

#include <stdio.h>
#include <tchar.h>
template<class T>
class ObjectPtr {
public:
   ObjectPtr<T> (T* pObj = NULL, bool bShared = false) :
      m_pObject(pObj), m_bObjectShared(bShared)
   {}
   ~ObjectPtr<T> ()
   {
      Detach();
   }
private:
   // private, unimplemented copy constructor and assignment operator
   // to guarantee that ObjectPtr<T> objects are not copied
   ObjectPtr<T> (const ObjectPtr<T>&);
   ObjectPtr<T>& operator = (const ObjectPtr<T>&);
public:
   T * GetObject ()
      { return m_pObject; }
   const T * GetObject () const
      { return m_pObject; }
   bool HasObject () const
      { return (GetObject()!=NULL); }
   bool IsObjectShared () const
      { return m_bObjectShared; }
   void ObjectShared (bool bShared)
      { m_bObjectShared = bShared; }
   bool IsNull () const
      { return !HasObject(); }
   void Attach (T* pObj, bool bShared = false)
   {
      Detach();
      if (pObj != NULL) {
         m_pObject = pObj;
         m_bObjectShared = bShared;
      }
   }
   void Detach (T** ppObject = NULL)
   {
      if (ppObject != NULL) {
         *ppObject = m_pObject;
         m_pObject = NULL;
         m_bObjectShared = false;
      }
      else {
         if (HasObject()) {
            if (!IsObjectShared())
               delete m_pObject;
            m_pObject = NULL;
            m_bObjectShared = false;
         }
      }
   }
   void Detach (bool bDeleteIfNotShared)
   {
      if (HasObject()) {
         if (bDeleteIfNotShared && !IsObjectShared())
            delete m_pObject;
         m_pObject = NULL;
         m_bObjectShared = false;
      }
   }
   bool IsEqualTo (const T * pOther) const
      { return (GetObject() == pOther); }
public:
   T * operator -> ()
      { ASSERT(HasObject()); return m_pObject; }
   const T * operator -> () const
      { ASSERT(HasObject()); return m_pObject; }
   T & operator * ()
      { ASSERT(HasObject()); return *m_pObject; }
   const T & operator * () const
      {  ASSERT(HasObject()); return (const C &)(*m_pObject); }
   operator T * ()
      { return m_pObject; }
   operator const T * () const
      { return m_pObject; }
   operator bool() const
      { return (m_pObject!=NULL); }
   ObjectPtr<T>& operator = (T * pObj)
      { Attach(pObj, false); return *this; }
   bool operator == (const T * pOther) const
      { return IsEqualTo(pOther); }
   bool operator == (T * pOther) const
      { return IsEqualTo(pOther); }
   bool operator != (const T * pOther) const
      { return !IsEqualTo(pOther); }
   bool operator != (T * pOther) const
      { return !IsEqualTo(pOther); }
   bool operator == (const ObjectPtr<T>& other) const
      { return IsEqualTo(other.GetObject()); }
   bool operator != (const ObjectPtr<T>& other) const
      { return !IsEqualTo(other.GetObject()); }
   bool operator == (int pv) const
      { return (pv==NULL)? IsNull() : (LPVOID(m_pObject)==LPVOID(pv)); }
   bool operator != (int pv) const
      { return !(*this == pv); }
private:
   T * m_pObject;
   bool m_bObjectShared;
};

// Some concrete type that holds useful data
class SomeUsefulData {
public:
   SomeUsefulData () {}
   ~SomeUsefulData () {}
};

// Some concrete type that holds a heap-allocated instance of
// SomeUsefulData
class SomeContainer {
public:
   SomeContainer (SomeUsefulData* pUsefulData)
   {
      m_pData = pUsefulData;
   }
   ~SomeContainer ()
   {
      // nothing to do here
   }
public:
   bool EvaluateSomeCondition ()
   {
      // fake condition check to give us an expression
      // to use in ?: operator below
      return true;
   }
   SomeUsefulData* Foo ()
   {
      // this usage of the ?: operator generates a C2248
      // error b/c it's attempting to call the copy
      // constructor on ObjectPtr<T>
      return EvaluateSomeCondition() ? m_pData : NULL;
      /**********[ DISCUSSION ]**********
      The following equivalent constructs compile
      w/out error and behave correctly:

      (1) explicit cast to SomeUsefulData* as a comiler hint
      return EvaluateSomeCondition() ? (SomeUsefulData *)m_pData : NULL;

      (2) if/else instead of ?:
      if (EvaluateSomeCondition())
         return m_pData;
      else
         return NULL;

      (3) skip the condition check and return m_pData as a
          SomeUsefulData* directly
      return m_pData;
      **********[ END DISCUSSION ]**********/
   }
private:
   ObjectPtr<SomeUsefulData> m_pData;
};

int _tmain(int argc, _TCHAR* argv[])
{
   return 0;
}

The constructors and destructors should not have the class's template parameters: 构造函数和析构函数不应该具有类的模板参数:

   ObjectPtr(T* pObj = NULL, bool bShared = false) :
      m_pObject(pObj), m_bObjectShared(bShared)
   {}

(note the lack of <T> ) (注意缺少<T>

But I think this is unrelated. 但我认为这是无关紧要的。 See my answer below... 请参阅下面的答案......

I don't own an actual copy of the C++ standard, but from this draft , page 102-103, a statement is ill-formed if, for expression ? E1 : E2 我没有C ++标准的实际副本,但是从第102-103页的草案中 ,如果expression ? E1 : E2 ,那么声明是不正确的expression ? E1 : E2 expression ? E1 : E2 , with types T1 and T2, and if T1 and T2 do not have an inheritance relationship, and one is an rvalue, then, expression ? E1 : E2 ,T1和T2类型,如果T1和T2没有继承关系,一个是rvalue,那么,

Using this process, it is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand. 使用该过程,确定是否可以转换第二操作数以匹配第三操作数,以及是否可以转换第三操作数以匹配第二操作数。 If both can be converted, or one can be converted but the conversion is ambiguous, the program is ill-formed. 如果两者都可以转换,或者一个可以转换,但转换不明确,则程序格式不正确。 If neither can be converted, the operands are left unchanged and further checking is performed as described below. 如果两者都不能被转换,则操作数保持不变并且如下所述执行进一步检查。 If exactly one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section. 如果只能进行一次转换,则将该转换应用于所选操作数,并使用转换后的操作数代替本节其余部分的原始操作数。

This seems to suggest that your statement is ill-formed (since you have a non-explicit constructor of ObjectPtr as well as operator T* ), but as I said I don't have the actual standard. 这似乎表明你的语句是ObjectPtr (因为你有一个ObjectPtr的非显式构造函数以及operator T* ),但正如我所说,我没有实际的标准。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM