2017-08-23 14 views
20

opsiyonel aşağıdaki kodla Verilen:Farklı sonuçlar std için döküm :: <T>

#include <iostream> 
#include <optional> 

struct foo 
{ 
    explicit operator std::optional<int>() { 
     return std::optional<int>(1); 
    } 
    explicit operator int() { 
     return 0; 
    } 
}; 

int main() 
{ 
    foo my_foo; 
    std::optional<int> my_opt(my_foo); 
    std::cout << "value: " << my_opt.value() << std::endl; 
} 

gcc 7.2.0 writesvalue: 1.

MSVC 2017 (15.3) ve clang 4.0.0 however writevalue: 0.

C++ standardına göre hangisi doğrudur?

cevap

18

Bu, doğrudan başlatma olduğundan, enumerate the constructors ve en iyisini seçin. std::optional için ilgili kurucular:

constexpr optional(const optional& other); // (2) 
constexpr optional(optional&& other) noexcept(/* see below */); // (3) 

template < class U = value_type > 
/* EXPLICIT */ constexpr optional(U&& value); // (8), with U = foo& 

Her ikisi de (intfoo& den constructible ve foo tutun hepsi ne std::in_place_t ne de std::optional<int>, eğer (8) sadece aşırı yük çözünürlükte katılır), ancak (8) tam bir eşleşme olduğunu yaşayabilir (2) ve (3), kullanıcı tanımlı bir dönüşüm gerektirirken, tercih edilmelidir. gcc burada yanlış. Bununla birlikte, gcc, (3)'u da istememektedir. Sadece my_opt'u my_foo'u optional<int>'a dönüştürmenin sonucundan doğrudan başlatır. gcc 7.2 baskılar 3 ama 1a hiçbiri, 1b veya 2 ile Bu program:

Bunun izin verilen bir rota olduğunu sanmıyorum. 81952 başvurdum.

+0

Her zaman aşırı yük çözünürlüğünün şablonlar tercih etmediğini düşündüm. Neden burası farklı? – Rakete1111

+6

@ Rakete1111 Burada farklı değil. Aşırı yük çözünürlüğü "her zaman" şablon içermez. Eşdeğer dönüşüm dizisi sıralamalarına sahip iki aday göz önüne alındığında, tiebreakerlerden biri, şablonsuz olanı tercih etmektir. Ancak burada eşdeğer dönüşüm dizisi sıralamalarımız yok. – Barry

+0

@Barry Aynı sıralamada iki dönüşümümüz yok mu? Biri 'int', hangisini (8) ve diğeri opsiyonel 'alırdı (2)? – Rakete1111

İlgili konular