müstehcen (bool)


24

C ++ 20, bir kurucunun açık yapılıp yapılmadığını koşullu olarak derleme zamanında seçen açık (bool) tanıtır .

Aşağıda burada bulduğum bir örnek var .

struct foo {

  // Specify non-integral types (strings, floats, etc.) require explicit construction.

  template <typename T>

  explicit(!std::is_integral_v<T>) foo(T) {}

};

foo a = 123; // OK

foo b = "123"; // ERROR: explicit constructor is not a candidate (explicit specifier evaluates to true)

foo c {"123"}; // OK

Biri bana explicit (bool)kullanmaktan başka bir kullanım alanı söyleyebilir std::is_integralmi?


1
Bir örnek, tuplebu özelliğe sahip olanlar gibi koşullu olarak açık kurucuları uygulamak çok daha kolay hale geliyor .
Praetorian

1
Doğru bir cevap değil, aynı zamanda onu tanıtan makaledeki motivasyona da bakabilirsiniz: wg21.link/p0892
N. Shead

Örnek: (kavramlarla birlikte), koşullu olarak sağlanan koşullu olarak açık bir kopya oluşturucuyu 3'ten 0'a uygulamak için gereken sayıda temel sınıfı keser
LF

Yanıtlar:


21

Motivasyonun kendisi makalede görülebilir .

Yapıcıları koşullu olarak açık hale getirmeye ihtiyaç vardır. Yani, istediğiniz:

pair<string, string> safe() {
    return {"meow", "purr"}; // ok
}

pair<vector<int>, vector<int>> unsafe() {
    return {11, 22}; // error
}

Birincisi iyi, bu yapıcılar örtük. Ama ikincisi kötü olurdu, bu yapıcılar explicit. C ++ 17 (veya kavramları olan C ++ 20) ile, bu işi yapmanın tek yolu iki yapıcı yazmaktır - explicitbiri değil biri:

template <typename T1, typename T2>
struct pair {
    template <typename U1=T1, typename U2=T2,
        std::enable_if_t<
            std::is_constructible_v<T1, U1> &&
            std::is_constructible_v<T2, U2> &&
            std::is_convertible_v<U1, T1> &&
            std::is_convertible_v<U2, T2>
        , int> = 0>
    constexpr pair(U1&&, U2&& );

    template <typename U1=T1, typename U2=T2,
        std::enable_if_t<
            std::is_constructible_v<T1, U1> &&
            std::is_constructible_v<T2, U2> &&
            !(std::is_convertible_v<U1, T1> &&
              std::is_convertible_v<U2, T2>)
        , int> = 0>
    explicit constexpr pair(U1&&, U2&& );    
};  

Bunlar neredeyse tamamen kopyalanmıştır ve bu kurucuların tanımları aynı olacaktır.

İle explicit(bool), yalnızca tek bir kurucu yazabilirsiniz - yapının koşullu olarak açık kısmı sadece explicit-specifier için yerelleştirilmiştir :

template <typename T1, typename T2>
struct pair {
    template <typename U1=T1, typename U2=T2,
        std::enable_if_t<
            std::is_constructible_v<T1, U1> &&
            std::is_constructible_v<T2, U2>
        , int> = 0>
    explicit(!std::is_convertible_v<U1, T1> ||
        !std::is_convertible_v<U2, T2>)
    constexpr pair(U1&&, U2&& );   
};

Bu amaç ile daha iyi eşleşir, yazmak için daha az koddur ve aşırı yük çözünürlüğü sırasında derleyicinin yapması için daha az iştir (çünkü aralarından seçim yapmak için daha az kurucu olduğundan).


1
C ++ 20 enable_if_t, muhtemelen kavramları kullanarak parçayı daha güzel ve daha basit bir kısıtlamaya değiştirme yeteneği de sağlar . Fakat bu, bu sorunun yanı sıra.
aschepler

2

Gördüğüm bir başka olası kullanım varyasyon şablonu ile:

Varsayılan olarak, explicityalnızca bir bağımsız değişkeni olan yapıcıya sahip olmak (dönüştürme istenmedikçe) genellikle iyidir .

yani

struct Foo
{
    template <typename ... Ts>
    explicit(sizeof...(Ts) == 1) Foo(Ts&&...);

    // ...
};

0

explicitGirişin std::string_viewyeni nesnenin çağrıdan sonra tutacağı görünüm benzeri bir tür (ham işaretçi ) olabilmesi için koşullu olarak gerektiren bir kullanım durumunu görebiliyordum (yalnızca görünümü kopyalama, ne demek istediğini değil, bağımlı görüntülenen nesnenin ömrü) veya değere benzer bir tür olabilir (dış yaşam boyu bağımlılığı olmadan bir kopyanın sahipliğini alır).

Böyle bir durumda, arayan görüntülenen nesneyi canlı tutmaktan sorumludur (callee orijinal nesneye değil bir görünüme sahiptir) ve dönüşüm dolaylı olarak yapılmamalıdır, çünkü dolaylı olarak oluşturulan nesnenin görüntülediği nesneyi yaşatmak. Buna karşılık, değer türleri için, yeni nesne kendi kopyasını alır, bu nedenle kopya pahalı olsa da, örtük bir dönüştürme gerçekleşirse kodu yanlış yapmaz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.