以下代码
#include <string>
#include <map>
#include <cassert>
struct AV {
explicit AV(std::string const&) {}
};
#if 1
static void check_cache_item(
std::map<std::string, std::string> const& items) // FIXME remove
{
assert(!items.empty());
}
#endif
static void check_cache_item(
std::map<std::string, AV> const& items)
{
assert(!items.empty());
}
int main()
{
check_cache_item({ { "id", "0" }, { "pk", "#0" } });
check_cache_item({ { "id", "0" }, { "pk", "#1" } });
check_cache_item({ { "id", AV{"0"} }, { "pk", AV{"#1"} } });
}
被g ++ 4.8.4,g ++ 5.3.0,clang ++ 3.9.0接受;但是g ++ 6.1.0给出了一个错误:
cci.cc: In function ‘int main()’:
cci.cc:25:55: error: call of overloaded ‘check_cache_item(<brace-enclosed initializer list>)’ is ambiguous
check_cache_item({ { "id", "0" }, { "pk", "#0" } });
^
cci.cc:10:17: note: candidate: void check_cache_item(const std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >&)
static void check_cache_item(
^~~~~~~~~~~~~~~~
cci.cc:16:17: note: candidate: void check_cache_item(const std::map<std::__cxx11::basic_string<char>, AV>&)
static void check_cache_item(
^~~~~~~~~~~~~~~~
cci.cc:26:55: error: call of overloaded ‘check_cache_item(<brace-enclosed initializer list>)’ is ambiguous
check_cache_item({ { "id", "0" }, { "pk", "#1" } });
^
cci.cc:10:17: note: candidate: void check_cache_item(const std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >&)
static void check_cache_item(
^~~~~~~~~~~~~~~~
cci.cc:16:17: note: candidate: void check_cache_item(const std::map<std::__cxx11::basic_string<char>, AV>&)
static void check_cache_item(
^~~~~~~~~~~~~~~~
cci.cc: At global scope:
cci.cc:10:17: warning: ‘void check_cache_item(const std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >&)’ defined but not used [-Wunused-function]
static void check_cache_item(
^~~~~~~~~~~~~~~~
如果我#ifdef第一个构造函数,那么每个编译器都会抛出一个错误(正确的,因为AV构造函数是显式的)。
这是G ++ 6.1.0中的回归吗?
答案 0 :(得分:14)
这是标准的一个令人惊讶且有些不幸的方面(我甚至称之为缺陷);它是复制列表初始化的重载决策规则(CWG 1228中确认的 [over.match.list] )与元素转发构造函数之间发生冲突的结果。 import UIKit
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
@IBOutlet weak var answer: UITextField!
var delegate: QuestionSelectorCellDelegate?
var pickOption: [String] = []
var pickerView:UIPickerView = UIPickerView()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
@IBAction func editBeginQuestionSelectorCell(sender: UITextField) {
pickerView = UIPickerView()
pickerView.delegate = self
sender.inputView = pickerView
}
func displayBlock(block: Block){
if block.answers != nil {
pickOption = block.answers! // block.answers! = ["blue","red","green"] for example
}
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickOption.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickOption[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if row < pickOption.count {
answer.text = pickOption[row]
delegate?.updateQuestionSelectorCell(self, rep: pickOption[row])
}
}
}
(根据n4387)。
gcc(&gt; = 6.1.0)拒绝你的程序是正确的; clang接受它是不正确的。早期版本的gcc接受你的程序,因为他们还没有实现n4387; clang接受您的计划,因为它excludes explicit constructors from consideration for overload resolution for copy-list-initialization,根据标准(Calling an explicit constructor with a braced-init list: ambiguous or not?)违反 [over.match.list]
如果我们剥离程序中无关紧要的方面,那就归结为一个简单的重载决策问题:
pair
此处struct A { explicit A(int, int); };
struct B { B(int, int); };
void f(A);
void f(B);
int main() { f({0, 0}); }
代表A
而pair<std::string const, AV>
代表B
。 pair<string const, string>
的构造函数是显式的,因为它涉及A
的显式构造函数n4387;但根据CWG 1228,复制列表初始化的规则:
[...]包括所有构造函数,但声明如果通过重载决策选择了显式构造函数,程序就会形成错误。 [...]
[...]在复制列表初始化中,如果选择了
AV
构造函数,则初始化是错误的。 [注意:这与其他情况([over.match.ctor],[over.match.copy])不同,其中只考虑转换构造函数进行复制初始化。此限制仅适用于此初始化是重载解析的最终结果的一部分。 - 结束记录]
因此,您的程序被正确考虑(在目前的标准下)是不明确的。
进一步阅读:What could go wrong if copy-list-initialization allowed explicit constructors?