代码之家  ›  专栏  ›  技术社区  ›  shane

C++强制强制STD::初始化函数到模板中的容器

  •  1
  • shane  · 技术社区  · 7 年前

    我无法将初始值设定项列表传递给模板化函数,然后调用将强制初始值设定项列表到容器的非模板化函数。但是,当跳过中间模板化函数时,它会编译。

    #include <iostream>
    #include <vector>
    
    struct MyLoader {
        static auto load(const std::vector<int> &v) {
            return v;
        }
    };
    
    template<typename Loader, typename... Args>
    auto makeVector(Args&&... args) {
        return Loader::load(std::forward<Args>(args)...);
    }
    
    int main() {
        auto v = makeVector<MyLoader>({ 8, 8, 8 });
    
        for (auto x : v) {
            std::cout << x << "\n";
        }
    }
    

    呈现错误:

    main.cpp: In instantiation of 'auto makeVector(Args&& ...) [with Loader = MyLoader; Args = {}]':
    main.cpp:18:46:   required from here
    main.cpp:13:24: error: no matching function for call to 'MyLoader::load()'
         return Loader::load(std::forward<Args>(args)...);
                ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    main.cpp:6:17: note: candidate: 'static auto MyLoader::load(const std::vector<int>&)'
         static auto load(const std::vector<int> &v) {
                     ^~~~
    main.cpp:6:17: note:   candidate expects 1 argument, 0 provided
    main.cpp: In function 'int main()':
    main.cpp:18:46: error: too many arguments to function 'auto makeVector(Args&& ...) [with Loader = MyLoader; Args = {}]'
         auto v = makeVector<MyLoader>({ 8, 8, 8 });
                                                  ^
    main.cpp:12:6: note: declared here
     auto makeVector(Args&&... args) {
          ^~~~~~~~~~
    main.cpp:18:10: error: 'void v' has incomplete type
         auto v = makeVector<MyLoader>({ 8, 8, 8 });
              ^
    main.cpp:20:19: error: unable to deduce 'auto&&' from 'v'
         for (auto x : v) {
    

    但是,以下内容非常完美:

    #include <iostream>
    #include <vector>
    
    struct MyLoader {
        static auto load(const std::vector<int> &v) {
            return v;
        }
    };
    
    int main() {
        auto v = MyLoader::load({ 8, 8, 8 });
    
        for (auto x : v) {
            std::cout << x << "\n";
        }
    }
    

    为什么初始值设定项列表没有强制到 std::vector 的参数 MyLoader::load() 在第一个例子中?

    1 回复  |  直到 7 年前
        1
  •  1
  •   max66    7 年前

    问题是 {8, 8, 8} 不能作为类型推导。

    如果将它传递给接收 const std::vector<int> ,一切顺利,因为编译器知道 _8、8、8_ 用于初始化 std::vector<int> .

    但如果将它传递给接收变量列表的函数( Args&&... args 的) 未知类型 参数,这不起作用,因为编译器不知道witch类型是 _8、8、8_ .

    建议:以可变方式传递值

    auto v = makeVector<MyLoader>(8, 8, 8);
    

    所以编译器可以检测 Args... 作为 int, int, int ,并传递给 load() 添加图形

    // ------------------V-----------------------------V   
    return Loader::load( { std::forward<Args>(args)... } );
    

    如果你真的(真的!)希望将th值传递给 makeVector() 作为初始化列表,可以作为数组截取它们

    template <typename Ldr, std::size_t Dim, typename Arg>
    auto makeVector (Arg(&&arg)[Dim])
    

    所以编译器可以推断( Arg 作为 int )以及尺寸( Dim , 3 万一 _8、8、8_ .

    但要解包数组,需要索引,所以需要一个函数助手。

    有点像

    template <typename Ldr, std::size_t ... Is, std::size_t Dim, typename Arg>
    auto makeVectorH (std::index_sequence<Is...> const &, Arg(&&arg)[Dim])
     { return Ldr::load({std::forward<Arg>(arg[Is])...}); }
    
    template <typename Ldr, std::size_t Dim, typename Arg>
    auto makeVector (Arg(&&arg)[Dim])
     { return makeVectorH<Ldr>(std::make_index_sequence<Dim>{},
                               std::forward<Arg[Dim]>(arg)); }
    

    下面是一个完全编译C++实例14的例子(但是我建议使用可变的参数)

    #include <vector>
    #include <utility>
    #include <iostream>
    
    struct MyLoader
     { static auto load(const std::vector<int> &v) { return v; } };
    
    template <typename Ldr, std::size_t ... Is, std::size_t Dim, typename Arg>
    auto makeVectorH (std::index_sequence<Is...> const &, Arg(&&arg)[Dim])
     { return Ldr::load({std::forward<Arg>(arg[Is])...}); }
    
    template <typename Ldr, std::size_t Dim, typename Arg>
    auto makeVector (Arg(&&arg)[Dim])
     { return makeVectorH<Ldr>(std::make_index_sequence<Dim>{},
                               std::forward<Arg[Dim]>(arg)); }
    
    int main ()
     {
       auto v = makeVector<MyLoader>({8, 8, 8});
    
       for (auto x : v)
            std::cout << x << "\n";
     }