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

参数列表中间的可变模板参数

  •  2
  • Felk  · 技术社区  · 6 年前

    我正试图指定一个将泛型函数作为参数的函数。函数的定义如下:

    template <typename TRet, typename... TsArgs>
    using Fun = TRet (*)(TsArgs...);
    

    如何指定将该泛型函数作为参数的泛型函数?我试过这个:

    template<typename TRet, typename... TsArgs, Fun<TRet, TsArgs...> F>
    TRet wrap(TsArgs... args) {
      return F(args...);
    }
    

    要包装此函数:

    bool foo(int x, double y) {
        return x < y;
    }
    

    这样地:

    Fun<bool, int, double> func = wrap<bool, int, double, foo>;
    

    然而,不幸的是,这并不能编译。GCC 8.1有以下错误信息:

    <source>:16:35: error: no matches converting function 'wrap' to type 'Fun<bool, int, double>' {aka 'bool (*)(int, double)'}
         Fun<bool, int, double> func = wrap<bool, int, double, foo>;
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    而clang 6有以下错误:

    <source>:16:35: error: address of overloaded function 'wrap' does not match required type 'bool (int, double)'
        Fun<bool, int, double> func = wrap<bool, int, double, foo>;
                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    但是,如果我替换 TsArgs 具有 int, double 就像签名一样 foo() 它编译得很好,让我相信参数列表中间的变量模板参数并不像我期望的那样工作。否则我怎么能实现我的目标呢?

    这是mcve:

    template <typename TRet, typename... TsArgs>
    using Fun = TRet (*)(TsArgs...);
    
    template<typename TRet, typename... TsArgs, Fun<TRet, TsArgs...> F>
    TRet wrap(TsArgs... args) {
        return F(args...);
    }
    
    bool foo(int x, double y) {
        return x < y;
    }
    
    int main() {
        Fun<bool, int, double> func = wrap<bool, int, double, foo>;
        return 0;
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   max66    6 年前

    auto

    wrapHelper

    template <typename T, T>
    struct wrapHelper;
    
    template <typename TRet, typename... TsArgs, Fun<TRet, TsArgs...> F>
    struct wrapHelper<Fun<TRet, TsArgs...>, F>
     {
       static TRet func (TsArgs ... args)
        { return F(args...); }
     };
    

    wrapper

    template <auto X>
    struct wrap : public wrapHelper<decltype(X), X>
     { };
    

    TRet TsArgs... foo

    Fun<bool, int, double> func = wrap<bool, int, double>::func<foo>;
    

    Fun<bool, int, double> func = wrap<foo>::func;
    

    auto func = wrap<foo>::func;
    

    #include <iostream>
    #include <type_traits>
    
    template <typename TRet, typename... TsArgs>
    using Fun = TRet (*)(TsArgs...);
    
    bool foo(int x, double y)
     { return x < y; }
    
    template <typename T, T>
    struct wrapHelper;
    
    template <typename TRet, typename... TsArgs, Fun<TRet, TsArgs...> F>
    struct wrapHelper<Fun<TRet, TsArgs...>, F>
     {
       static TRet func (TsArgs ... args)
        { return F(args...); }
     };
    
    template <auto X>
    struct wrap : public wrapHelper<decltype(X), X>
     { };
    
    int main()
     {   
       auto func { wrap<foo>::func };
    
       static_assert( std::is_same<decltype(func), Fun<bool, int, double>>{} );
    
       std::cout << func(1, 2.0) << std::endl;
     }
    
        2
  •  2
  •   max66    6 年前

    wrap TRet TArgs... func() Fun<TRet, TsArgs...>

    template <typename TRet, typename... TsArgs>
    struct wrap
     {
       template <Fun<TRet, TsArgs...> F>
       static TRet func (TsArgs ... args)
        { return F(args...); }
     };
    

    Fun<bool, int, double> func = wrap<bool, int, double>::func<foo>;
    

    #include <iostream>
    
    template <typename TRet, typename... TsArgs>
    using Fun = TRet (*)(TsArgs...);
    
    template <typename TRet, typename... TsArgs>
    struct wrap
     {
       template <Fun<TRet, TsArgs...> F>
       static TRet func (TsArgs ... args)
        { return F(args...); }
     };
    
    bool foo(int x, double y)
     { return x < y; }
    
    int main()
     {
       Fun<bool, int, double> func = wrap<bool, int, double>::func<foo>;
    
       std::cout << func(1, 2.0) << std::endl;
     }