GCC不能使用未定义的operator =

时间:2014-07-07 11:06:32

标签: c++ gcc implicit-conversion

我有一个代码:

#define CLI_DECLARE_PROPERTY_RW(OWNERNAME, TYPE, NAME)                   \
struct propclass_##NAME {                                                \
    DWORD dummy;                                                         \
    inline operator TYPE() {                                             \
        return CLI_CONTAINING_RECORD(this, OWNERNAME, NAME)-> get_##NAME ();    \
    }                                                                    \
    inline void operator=(const TYPE &src) {                             \
        CLI_CONTAINING_RECORD(this, OWNERNAME, NAME)-> set_##NAME (src); \
    }                                                                    \
} NAME;

...

    class CiStringSpecialEncoderWrapper
    {
        public:
        CLI_DECLARE_PROPERTY_RW(CiStringSpecialEncoderWrapper, INTERFACE_CLI_ISTRINGENCODER*, defEncoder)

...

specialEncoderText.defEncoder = encoder.getIfPtr(); // getIfPtr returns exact  INTERFACE_CLI_ISTRINGENCODER*

并收到错误:

error: no match for 'operator=' in 'specialEncoderText.cli::CiStringSpecialEncoderWrapper<cli::CCliPtr<cli::iStringSpecialEncoder> >::defEncoder = encoder.cli::CiStringEncoderWrapper<smartPtrType>::getIfPtr [with smartPtrType = cli::CCliPtr<cli::iStringEncoder>]()'
note: candidates are: void cli::CiStringSpecialEncoderWrapper<smartPtrType>::propclass_defEncoder::operator=(const cli::iStringEncoder*&) [with smartPtrType = cli::CCliPtr<cli::iStringSpecialEncoder>]
note:                 cli::CiStringSpecialEncoderWrapper<cli::CCliPtr<cli::iStringSpecialEncoder> >::propclass_defEncoder& cli::CiStringSpecialEncoderWrapper<cli::CCliPtr<cli::iStringSpecialEncoder> >::propclass_defEncoder::operator=(const cli::CiStringSpecialEncoderWrapper<cli::CCliPtr<cli::iStringSpecialEncoder> >::propclass_defEncoder&)

似乎GCC尝试使用默认的隐式operator =,这是未定义的。我怎么能解决这个问题?

我尝试使用第二个签名定义private operator =,但仍然存在歧义。

目前使用的GCC版本是4.4.1。以前使用过GCC v3.4,这段代码没有问题。

UPD01 最小,完整且可验证的示例

#include <iostream>

typedef unsigned long DWORD;
typedef unsigned long ULONG_PTR;
typedef char * PCHAR;

#if defined(_MSC_VER) || defined(DISABLE_GCC_OFFSETOF_WARNING_WORKAROUND)
    #define CLI_CONTAINING_RECORD(address, type, field) ((type *)( \
                                                      (PCHAR)(address) - \
                                                      (ULONG_PTR)(&((type *)0)->field)))
#else
    #define CLI_CONTAINING_RECORD(address, type, field) ((type *)( \
                                                      1+(PCHAR)(address) - \
                                                      (ULONG_PTR)(&((type *)1)->field)))
#endif


#define CLI_DECLARE_PROPERTY_RW(OWNERNAME, TYPE, NAME)                   \
struct propclass_##NAME {                                                \
    DWORD dummy;                                                         \
    /*propclass_##NAME() : dummy() {}*/                                      \
    inline operator TYPE() {                                             \
        return CLI_CONTAINING_RECORD(this, OWNERNAME, NAME)-> get_##NAME ();    \
    }                                                                    \
    inline void operator=(const TYPE &src) {                             \
        CLI_CONTAINING_RECORD(this, OWNERNAME, NAME)-> set_##NAME (src); \
    }                                                                    \
    /*private:*/                                                             \
    /*explicit propclass_##NAME(const propclass_##NAME &src) {} */            \
    /*inline void operator=(const propclass_##NAME &src) {}     */           \
                                                                         \
} NAME;


struct SomeInterface
{
 int dummy;
 void doJob() { std::cout<<"SomeInterface::doJob\n"; }
};

class CTest
{
    SomeInterface *psf;

 public:

    SomeInterface* get_defEncoder( )
       {
        return psf;
       }

    void set_defEncoder( const SomeInterface*  &_defEncoder
                       )
       {
        psf = (SomeInterface*)_defEncoder;
       }

    CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );

};

SomeInterface sf;

int main(int argc, char* argv[])
{
    CTest test;

    test.defEncoder = &sf; // (SomeInterface*)0;

    SomeInterface *pif = test.defEncoder;
    pif->doJob();
}

1 个答案:

答案 0 :(得分:2)

g ++ 4.9.0为您的MCVE提供了这些错误:

main.cpp:58:64: warning: extra ';' [-Wpedantic]
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
                                                                ^
main.cpp: In function 'int main(int, char**)':
main.cpp:68:21: error: no match for 'operator=' (operand types are 'CTest::propclass_defEncoder' and 'SomeInterface*')
     test.defEncoder = &sf; // (SomeInterface*)0;
                     ^
main.cpp:68:21: note: candidates are:
main.cpp:25:17: note: void CTest::propclass_defEncoder::operator=(const SomeInterface*&)
     inline void operator=(const TYPE &src) {                             \
                 ^
main.cpp:58:5: note: in expansion of macro 'CLI_DECLARE_PROPERTY_RW'
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
     ^
main.cpp:25:17: note:   no known conversion for argument 1 from 'SomeInterface*' to 'const SomeInterface*&'
     inline void operator=(const TYPE &src) {                             \
                 ^
main.cpp:58:5: note: in expansion of macro 'CLI_DECLARE_PROPERTY_RW'
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
     ^
main.cpp:19:8: note: CTest::propclass_defEncoder& CTest::propclass_defEncoder::operator=(const CTest::propclass_defEncoder&)
 struct propclass_##NAME {                                                \
        ^
main.cpp:58:5: note: in expansion of macro 'CLI_DECLARE_PROPERTY_RW'
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
     ^
main.cpp:19:8: note:   no known conversion for argument 1 from 'SomeInterface*' to 'const CTest::propclass_defEncoder&'
 struct propclass_##NAME {                                                \
        ^
main.cpp:58:5: note: in expansion of macro 'CLI_DECLARE_PROPERTY_RW'
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
     ^
main.cpp:19:8: note: CTest::propclass_defEncoder& CTest::propclass_defEncoder::operator=(CTest::propclass_defEncoder&&)
 struct propclass_##NAME {                                                \
        ^
main.cpp:58:5: note: in expansion of macro 'CLI_DECLARE_PROPERTY_RW'
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
     ^
main.cpp:19:8: note:   no known conversion for argument 1 from 'SomeInterface*' to 'CTest::propclass_defEncoder&&'
 struct propclass_##NAME {                                                \
        ^
main.cpp:58:5: note: in expansion of macro 'CLI_DECLARE_PROPERTY_RW'
     CLI_DECLARE_PROPERTY_RW(CTest, SomeInterface*, defEncoder );
     ^
main.cpp: At global scope:
main.cpp:64:14: warning: unused parameter 'argc' [-Wunused-parameter]
 int main(int argc, char* argv[])
              ^
main.cpp:64:31: warning: unused parameter 'argv' [-Wunused-parameter]
 int main(int argc, char* argv[])

                           ^

首先要检查的是:在寻找operator=敏感时使用的类型是什么?

no match for 'operator=' (operand types are 'CTest::propclass_defEncoder'
and 'SomeInterface*')

到目前为止看起来不错。然后g ++列出它考虑的所有候选函数。你在列表中预期的那个?烨:

note: void CTest::propclass_defEncoder::operator=(const SomeInterface*&)

然后在那之后,它说

note:    no known conversion for argument 1 from 'SomeInterface*'
         to 'const SomeInterface*&'

啊哈。由于您使用的是预处理器,因此const TYPE&不是const TYPE的引用。它只是将const标记放在前面,给出const SomeInterface*&,这是对非const指针(对const数据)的引用。但由于输入SomeInterface*参数未指向const数据,因此您无法将该类型的引用绑定到它。

您可能希望operator=具有参数类型SomeInterface* const&。你可以通过在宏中放置TYPE const&而不是const TYPE&来实现这一点,至少在这种情况下如此。但为了更安全一点,你可以使用typedef并使用C ++的实际类型语义:

#define CLI_DECLARE_PROPERTY_RW(OWNERNAME, TYPE, NAME)                   \
struct propclass_##NAME {                                                \
    typedef TYPE property_type;                                          \
    DWORD dummy;                                                         \
    /*propclass_##NAME() : dummy() {}*/                                      \
    inline operator property_type() {                                    \
        return CLI_CONTAINING_RECORD(this, OWNERNAME, NAME)-> get_##NAME ();    \
    }                                                                    \
    inline void operator=(const property_type &src) {                    \
        CLI_CONTAINING_RECORD(this, OWNERNAME, NAME)-> set_##NAME (src); \
    }                                                                    \
} NAME;
相关问题