这个尾随返回类型声明的目的是什么?

时间:2017-09-15 01:03:00

标签: c++ c++17 trailing-return-type

我试图理解cppreference为std::visit提供的示例。以下是该链接的示例:

    #include <iomanip>
    #include <iostream>
    #include <string>
    #include <type_traits>
    #include <variant>
    #include <vector>


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

    using var_t = std::variant<int, long, double, std::string>;

    template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

    int main() {
        std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
        for(auto& v: vec) {
            // void visitor, only called for side-effects
            std::visit([](auto&& arg){std::cout << arg;}, v);

            // value-returning visitor. A common idiom is to return another variant
            var_t w = std::visit([](auto&& arg) -> var_t {return arg + arg;}, v);

            std::cout << ". After doubling, variant holds ";
            // type-matching visitor: can also be a class with 4 overloaded operator()'s
            std::visit([](auto&& arg) {
                using T = std::decay_t<decltype(arg)>;
                if constexpr (std::is_same_v<T, int>)
                    std::cout << "int with value " << arg << '\n';
                else if constexpr (std::is_same_v<T, long>)
                    std::cout << "long with value " << arg << '\n';
                else if constexpr (std::is_same_v<T, double>)
                    std::cout << "double with value " << arg << '\n';
                else if constexpr (std::is_same_v<T, std::string>)
                    std::cout << "std::string with value " << std::quoted(arg) << '\n';
                else 
                    static_assert(always_false<T>::value, "non-exhaustive visitor!");
            }, w);
        }

        for (auto& v: vec) {
            std::visit(overloaded {
                [](auto arg) { std::cout << arg << ' '; },
                [](double arg) { std::cout << std::fixed << arg << ' '; },
                [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
            }, v);
        }
    }

我对overloaded声明特别感兴趣:

    template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
    template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

第一个是有意义的 - 结构overloaded正在为它封装的每个类型的构造函数声明。但是我不明白第二个目的。这似乎是一个类似于:

的函数声明
template<class... Ts> overloaded<Ts...> overloaded(Ts...);

但是函数永远不会定义,所以如何在后面的示例中使用它?如果这只是一个构造函数,那么为什么它不需要overloaded::前缀,身体在哪里呢?我想我只是误解了尾随返回类型声明“扩展”的内容,因此对overloaded(Ts...)声明所完成的内容的任何见解都将不胜感激。

0 个答案:

没有答案