gpt4 book ai didi

c++ - 如何使这个模板参数可变?

转载 作者:搜寻专家 更新时间:2023-10-31 00:00:02 24 4
gpt4 key购买 nike

假设我有一个这样的模板声明:

template <class A, class B, class C = A (&)(B)>

我如何才能拥有可变数量的 C 类型的对象?执行 class C ...c = x 是行不通的,因为可变模板参数不能有默认值。所以这就是我尝试过的:

template <typename T>
struct helper;

template <typename F, typename B>
struct helper<F(B)> {
typedef F (&type)(B);
};

template <class F, class B, typename helper<F(B)>::type ... C>
void f(C ...c) { // error

}

但直到最后一部分,我才收到错误消息。我不认为我这样做是对的。我在这里做错了什么?

最佳答案

我认为您可以使用以下方法。首先,一些类型特征的机制。这使您可以确定参数包中的类型是否同类(我猜您希望所有函数都具有相同的签名):

struct null_type { };

// Declare primary template
template<typename... Ts>
struct homogeneous_type;

// Base step
template<typename T>
struct homogeneous_type<T>
{
using type = T;
static const bool isHomogeneous = true;
};

// Induction step
template<typename T, typename... Ts>
struct homogeneous_type<T, Ts...>
{
// The underlying type of the tail of the parameter pack
using type_of_remaining_parameters = typename
homogeneous_type<Ts...>::type;

// True if each parameter in the pack has the same type
static const bool isHomogeneous =
is_same<T, type_of_remaining_parameters>::value;

// If isHomogeneous is "false", the underlying type is a fictitious type
using type = typename conditional<isHomogeneous, T, null_type>::type;
};

// Meta-function to determine if a parameter pack is homogeneous
template<typename... Ts>
struct is_homogeneous_pack
{
static const bool value = homogeneous_type<Ts...>::isHomogeneous;
};

然后,使用更多类型特征来确定泛型函数的签名:

template<typename T>
struct signature;

template<typename A, typename B>
struct signature<A (&)(B)>
{
using ret_type = A;
using arg_type = B;
};

最后,这是定义可变函数模板的方式:

template <typename... F>
void foo(F&&... f)
{
static_assert(is_homogeneous_pack<F...>::value, "Not homogeneous!");
using fxn_type = typename homogeneous_type<F...>::type;

// This was template parameter A in your original code
using ret_type = typename signature<fxn_type>::ret_type;

// This was template parameter B in your original code
using arg_type = typename signature<fxn_type>::arg_type;

// ...
}

这是一个简短的测试:

int fxn1(double) { }
int fxn2(double) { }
int fxn3(string) { }

int main()
{
foo(fxn1, fxn2); // OK
foo(fxn1, fxn2, fxn3); // ERROR! not homogeneous signatures
return 0;
}

最后,如果您在拥有该参数包后需要做什么的灵感,您可以查看 a small library I wrote (取自此答案中使用的机器的哪一部分)。调用参数包 F...f 中所有函数的简单方法如下(来自@MarkGlisse):

initializer_list<int>{(f(forward<ArgType>(arg)), 0)...};

您可以轻松地将其包装在宏中(只需查看 Mark 对我发布的链接的回答)。

这是一个完整的、可编译的程序:

#include <iostream>
#include <type_traits>

using namespace std;

struct null_type { };

// Declare primary template
template<typename... Ts>
struct homogeneous_type;

// Base step
template<typename T>
struct homogeneous_type<T>
{
using type = T;
static const bool isHomogeneous = true;
};

// Induction step
template<typename T, typename... Ts>
struct homogeneous_type<T, Ts...>
{
// The underlying type of the tail of the parameter pack
using type_of_remaining_parameters = typename
homogeneous_type<Ts...>::type;

// True if each parameter in the pack has the same type
static const bool isHomogeneous =
is_same<T, type_of_remaining_parameters>::value;

// If isHomogeneous is "false", the underlying type is a fictitious type
using type = typename conditional<isHomogeneous, T, null_type>::type;
};

// Meta-function to determine if a parameter pack is homogeneous
template<typename... Ts>
struct is_homogeneous_pack
{
static const bool value = homogeneous_type<Ts...>::isHomogeneous;
};

template<typename T>
struct signature;

template<typename A, typename B>
struct signature<A (&)(B)>
{
using ret_type = A;
using arg_type = B;
};

template <typename F>
void foo(F&& f)
{
cout << f(42) << endl;
}

template <typename... F>
void foo(typename homogeneous_type<F...>::type f, F&&... fs)
{
static_assert(is_homogeneous_pack<F...>::value, "Not homogeneous!");
using fxn_type = typename homogeneous_type<F...>::type;

// This was template parameter A in your original code
using ret_type = typename signature<fxn_type>::ret_type;

// This was template parameter B in your original code
using arg_type = typename signature<fxn_type>::arg_type;

cout << f(42) << endl;
foo(fs...);
}

int fxn1(double i) { return i + 1; }
int fxn2(double i) { return i * 2; }
int fxn3(double i) { return i / 2; }
int fxn4(string s) { return 0; }

int main()
{
foo(fxn1, fxn2, fxn3); // OK

// foo(fxn1, fxn2, fxn4); // ERROR! not homogeneous signatures

return 0;
}

关于c++ - 如何使这个模板参数可变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14270843/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com