GCC 不能使用未定义的运算符=
GCC can't use undefined operator=
我有一个代码:
#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试图使用默认的隐式操作符=,这是未定义的。我怎样才能解决这个问题?
我尝试用第二个签名定义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::doJobn"; }
};
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();
}
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;
相关文章:
- 一元"运算符"未在C++中定义
- 体系结构x86_64的未定义符号:std:terminate(),typeinfo,运算符delete[],运算符new
- 未定义的引用和运算符 << vs me
- C++:对函子重载调用运算符的未定义引用
- 对模板运算符的未定义引用,其定义位于同一头文件中
- 在 tensorflow-GPU 中使用用户运算符时未定义的符号>=1.15
- 为什么T是未定义的?我正在尝试实现一个用于双链表的节点类,它不喜欢我使用友元运算符后的T
- 调用提取重加载器会产生对"运算符"的未定义引用错误>>
- 创建指针是否超过非数组指针的末尾,而不是从 C++17 中的一元运算符和未定义的行为派生?
- 编译Qt项目给出了对运算符delete(void*,unsigned int)的未定义引用
- 在 C 和 C++ 中,使用逗号运算符的表达式是否未定义"a = b, ++a;"?
- 未定义对运算符的引用!= 使用 std::unordered_set 时
- C2676 - 二进制'++'未定义此运算符
- 尝试编写进程内存并获取用户定义的文字运算符未找到
- 未定义 Lambda 复制分配运算符
- 为什么要重载以前未定义的运算符
- std::可选运算符*() 和运算符>() - 未定义的行为
- std::映射运算符[]--未定义的行为
- 获取函数运算符<未定义的引用
- 错误:"运算符 []"未定义