【问题标题】:Parameterized non-type template parameters?参数化的非类型模板参数?
【发布时间】:2014-05-18 12:02:42
【问题描述】:

是否可以参数化非类型模板参数?我正在尝试生成一个 thunk,它将其参数转发到基于一些运行时检查的两个编译时间常量函数之一,以希望得到一些符合以下内容的内容:

#include <stdlib.h>

int a(int, int, char) {
    return 0;
}

int b(int, int, char) {
    return 0;
}

// This doesn't work
template<typename ReturnType, typename... Params>
template<ReturnType (*first)(Params...), ReturnType (*second)(Params...)>
ReturnType coin_flip(Params... params) {
    if (rand() % 2) {
        return first(params...);
    } else {
        return second(params...);
    }
}

int main() {
    return coin_flip<a, b>(1, 2, '3');
}

【问题讨论】:

  • 是的,但不推断所述参数。有针对 C++1y/1z 的提议。我不记得他们是否进入了 1 年。

标签: c++ templates c++11 variadic-templates auto-generate


【解决方案1】:

您可以将函数作为参数传递给coin_flip(而不是模板参数):

#include <iostream>
#include <cstdlib>
#include <type_traits>

int a(int, int, char) {
    std::cout << 'a';
    return 0;
}

int b(int, int, char) {
    std::cout << 'b';
    return 0;
}

template<typename FnA, typename FnB, typename... Params>
typename std::result_of<FnA&(Params...)>::type
coin_flip(FnA a, FnB b, Params... params) {
    // For testing, the condition is removed here
    a(params...);
    return b(params...);
}

int main() {
    coin_flip(a, b, 1, 2, '3');
    std::cout << '\n';
    return  0;
}

【讨论】:

    【解决方案2】:

    有一个使用类型模板参数(通过std::integral_constant)和宏的解决方法:

    #include <type_traits>
    
    template <typename, typename>
    struct coin_flip;
    
    template
        <
            typename ReturnType,
            typename... Params,
            ReturnType (*first)(Params...),
            ReturnType (*second)(Params...)
        >
    struct coin_flip
        <
            std::integral_constant<ReturnType (*)(Params...), first>,
            std::integral_constant<ReturnType (*)(Params...), second>
        >
    {
        static
        ReturnType call(Params&&... params) {
            if (rand() % 2) {
                return first(std::forward<Params>(params)...);
            } else {
                return second(std::forward<Params>(params)...);
            }
        }
    };
    
    #define FUNCTION_CONSTANT(f) std::integral_constant<decltype(&f), f>
    
    #define COIN_FLIP(first, second, ...) \
        coin_flip<FUNCTION_CONSTANT(first), FUNCTION_CONSTANT(second)>::call(__VA_ARGS__)
    

    使用示例:

    std::cout << COIN_FLIP(a, b, 1, 2, '3') << std::endl;
    

    【讨论】:

      【解决方案3】:

      以下可能会有所帮助:

      template<typename F, F f1, F f2, typename... Params>
      auto coin_flip(Params&&... params) -> decltype(f1(std::forward<Params>(params)...)) {
          if (rand() % 2) {
              return f1(std::forward<Params>(params)...);
          } else {
              return f2(std::forward<Params>(params)...);
          }
      }
      
      int main() {
          return coin_flip<decltype(&a), &a, &b>(1, 2, '3');
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多