C++ 11中的非类型可变参数函数模板

Mot*_*tti 25 c++ variadic-templates c++11

我看到一篇博客帖子使用了非类型的可变参数模板(目前gcc不支持,只有clang支持).

template <class T, size_t... Dimensions>
struct MultiDimArray { /* ... */ };
Run Code Online (Sandbox Code Playgroud)

帖子中的示例编译得很好,但我没能使用函数模板.

任何人都可以帮助找出正确的语法(如果存在)?

int max(int n) { return n; } // end condition

template <int... N> // replacing int... with typename... works
int max(int n, N... rest) // !! error: unknown type name 'N'
{
    int tmp = max(rest...);
    return n < tmp? tmp : n;
}

#include <iostream>
int main() 
{
   std::cout << max(3, 1, 4, 2, 5, 0) << std::endl;   
}
Run Code Online (Sandbox Code Playgroud)

Kon*_*lph 14

您只是混淆类型名称和非类型名称.你想要的只是不起作用.

可以在函数中使用可变参数非类型模板,但不能在(非模板)参数中使用:

template <int N, int... Rest>
int max()
{
    int tmp = max<Rest...>();
    return N < tmp ? tmp : N;
}
Run Code Online (Sandbox Code Playgroud)
std::cout << max<3, 1, 4, 2, 5, 0>() << std::endl;
Run Code Online (Sandbox Code Playgroud)

...虽然我没有对此进行测试,但我不确定这应该如何工作,因为您需要将部分专业化作为基本案例.您可以通过调度到部分专用的结构来解决这个问题:

template <int N, int... Rest>
struct max_t {
    static int const value = max_t<Rest...>::value > N ? max_t<Rest...>::value : N;
};

template <int N>
struct max_t<N> {
    static int const value = N;
};


template <int... NS>
int max()
{
    return max_t<NS...>::value;
}
Run Code Online (Sandbox Code Playgroud)

这会奏效.

  • @Motti`template <int I> void foo(I i);`将是荒谬的.在进行可变参数之前,您需要了解它. (5认同)
  • @Motti:如果您不是在寻找编译时函数,那么您也不会寻找非类型模板参数.非类型模板参数必须是编译时常量表达式. (3认同)

par*_*203 10

这将打印出所有元素,get max可以类似地实现

template <int N>
void foo(){
  cout << N << endl;
}

template <int N, int M, int ... Rest>
void foo(){
  cout << N << endl;
  foo<M, Rest...>();
}


int main(){
  foo<1, 5, 7>();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢你如何避免模棱两可的方式. (3认同)

Luc*_*ton 7

以下是定义仅接受int参数的可变参数函数模板的两种方法.第一个在实例化时生成硬错误,第二个使用SFINAE:

template<typename... T>
struct and_: std::true_type {};

template<typename First, typename... Rest>
struct and_
: std::integral_constant<
    bool
    , First::value && and_<Rest...>::value
> {};

template<typename... T>
void
foo(T... t)
{
    static_assert(
        and_<std::is_same<T, int>...>::value
        , "Invalid parameter was passed" );
    // ...
}

template<
    typename... T
    , typename = typename std::enable_if<
        and_<std::is_same<T, int>...>::value
    >::type
>
void
foo(T... t)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

如您所见,此处不使用非类型模板参数.