我有一个代码:
#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();
}
答案 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;