c++ - एक गैर-वैकल्पिक स्वीकार करने के लिए एक विकल्प को स्वीकार करने के लिए एक फ़ंक्शन बनाएं?




templates c++17 (3)

एक और संस्करण। यह एक कुछ भी शामिल नहीं करता है:

template <typename T>
void f(T&& t) {
    std::optional opt = std::forward<T>(t);
}

क्लास टेम्प्लेट तर्क कटौती पहले से ही यहां सही काम करती है। यदि t एक optional , तो प्रतिलिपि कटौती उम्मीदवार को पसंद किया जाएगा और हमें उसी प्रकार का वापस मिलेगा। अन्यथा, हम इसे लपेटते हैं।

मैं सिंथैटिक शुगर लिखने की कोशिश कर रहा हूं, एक सनक-शैली में, std::optional । कृपया ध्यान रखें:

template<class T>
void f(std::optional<T>)
{}

जैसा कि, इस फ़ंक्शन को एक गैर-वैकल्पिक T 1 (उदाहरण के लिए एक int ) के साथ नहीं बुलाया जा सकता है, भले ही T से std::optional<T> 2 में रूपांतरण मौजूद हो।

एक अधिभार 3 को परिभाषित किए बिना f को एक std::optional<T> या T (कॉलर साइट पर एक वैकल्पिक में परिवर्तित) को स्वीकार करने का एक तरीका है ?

1) f(0) : error: no matching function for call to 'f(int)' और note: template argument deduction/substitution failed ( demo )।
2) क्योंकि टेम्पलेट तर्क कटौती रूपांतरणों पर विचार नहीं करती है।
3) ओवरलोडिंग एक अनियंत्रित कार्य के लिए एक स्वीकार्य समाधान है, लेकिन जब आप operator+(optional, optional) जैसे द्विआधारी कार्य करते हैं, और त्रिगुट, 4-आर्य, आदि कार्यों के लिए दर्द होता है, तो यह एक झुंझलाहट है।


एक और संस्करण। यह एक लेखन लक्षण शामिल नहीं करता है:

template <typename T>
struct make_optional_t {
    template <typename U>
    auto operator()(U&& u) const {
        return std::optional<T>(std::forward<U>(u));
    }
};

template <typename T>
struct make_optional_t<std::optional<T>> {
    template <typename U>
    auto operator()(U&& u) const {
        return std::forward<U>(u);
    }
};

template <typename T>
inline make_optional_t<std::decay_t<T>> make_optional;

template <typename T>
void f(T&& t){
    auto opt = make_optional<T>(std::forward<T>(t));
}

वैकल्पिक के रूप में तर्क के रूप में लेने के बजाय कटौती योग्य टेम्पलेट पैरामीटर लें:

template<class T>
struct is_optional : std::false_type{};

template<class T>
struct is_optional<std::optional<T>> : std::true_type{};

template<class T, class = std::enable_if_t<is_optional<std::decay_t<T>>::value>>
constexpr decltype(auto) to_optional(T &&val){
    return std::forward<T>(val);
}

template<class T, class = std::enable_if_t<!is_optional<std::decay_t<T>>::value>>
constexpr std::optional<std::decay_t<T>> to_optional(T &&val){
    return { std::forward<T>(val) };
}

template<class T>
void f(T &&t){
    auto opt = to_optional(std::forward<T>(t));
}

int main() {
    f(1);
    f(std::optional<int>(1));
}

जीवंत उदाहरण





template-deduction