我有一个同时包含复制构造函数和构造函数的类std::reference_wrapper
:
#include <functional>
#include <iostream>
class Class {
public:
Class() {
std::cout << "Class()" << std::endl;
}
Class(Class const &) {
std::cout << "Class(Class const &)" << std::endl;
}
Class(std::reference_wrapper<Class>) {
std::cout << "Class(std::reference_wrapper<Class>)" << std::endl;
}
Class(std::reference_wrapper<const Class>) {
std::cout << "Class(std::reference_wrapper<const Class>)" << std::endl;
}
};
int main() {
Class a;
Class b = a;
Class c = std::ref(a);
Class d = std::cref(a);
}
正常编译时(g++ --std=c++17 test.cpp
),这可以按需运行,按顺序调用四个构造函数:
$ ./a.exe
Class()
Class(Class const &)
Class(std::reference_wrapper<Class>)
Class(std::reference_wrapper<const Class>)
但是,使用-pedantic
(即g++ --std=c++17 -pedantic test.cpp
)进行编译会导致以下错误(以及std::cref
的另一个等效错误):
test.cpp:23:22: error: conversion from 'std::reference_wrapper<Class>' to 'Class' is ambiguous
Class c = std::ref(a);
^
note: candidate: std::reference_wrapper<_Tp>::operator _Tp&() const [with _Tp = Class]
note: candidate: Class::Class(std::reference_wrapper<Class>)
为什么这样(即我如何违反标准,在Conversion constructor vs. conversion operator: precedence中回答),以及如何以标准符合的方式在没有-pedantic
的情况下实现结果
$ g++ --version
g++.exe (Rev1, Built by MSYS2 project) 7.2.0
答案 0 :(得分:1)
如何以符合标准的方式实现结果而不是-pedantic?
在您的情况下创建具有完全匹配的重载:
Class(std::reference_wrapper<Class>&&) {
std::cout << "Class(std::reference_wrapper<Class>)" << std::endl;
}
Class(std::reference_wrapper<const Class>&&) {
std::cout << "Class(std::reference_wrapper<const Class>)" << std::endl;
}
答案 1 :(得分:1)
将构造函数定义为operator T& () const
,以避免与std::reference_wrapper
类中定义的转换运算符#include <functional>
#include <iostream>
class Class {
public:
Class() {
std::cout << "Class()" << std::endl;
}
Class(Class const &) {
std::cout << "Class(Class const &)" << std::endl;
}
explicit Class(std::reference_wrapper<Class>) {
std::cout << "Class(std::reference_wrapper<Class>)" << std::endl;
}
explicit Class(std::reference_wrapper<const Class>) {
std::cout << "Class(std::reference_wrapper<const Class>)" << std::endl;
}
};
int main() {
Class a;
Class b = a;
Class c = std::ref(a); // call Class(Class const &) trough the conversion operator
Class d(std::ref(a)); // call Class(std::reference_wrapper<Class>)
Class e = std::cref(a); // call Class(Class const &) trough the conversion operator
Class f(std::cref(a)); // call Class(std::reference_wrapper<const Class>)
}
发生冲突:
Class(Class const &)
或者删除构造函数重载3和4以始终使用复制构造函数{{1}}。
没有迂腐选项就没有错误,因为GCC优先考虑复制构造函数而不是转换运算符,但这不是标准的一部分,没有定义优先级,因此存在冲突。