gpt4 book ai didi

c++ - 如何使特征接受参数包?

转载 作者:行者123 更新时间:2023-12-01 14:52:18 25 4
gpt4 key购买 nike

我定义了一些这样的类型特征:

template <typename T>
struct has_something
{
static constexpr bool value = false;
};

template <>
struct has_something<int>
{
static constexpr bool value = true;
};

template <typename T>
constexpr bool has_something_v = has_something<T>::value;


函数模板是 has_something_v是对函数参数的要求:

template <typename T, typename = std::enable_if_t<has_something_v<T>>>
void some_function(const T temp)
{
}

当我用错误的类型调用它时:

struct wrong_type
{
};

void f ()
{
some_function(wrong_type());
}

编译器给我一个正确的错误信息:

/tmp/untitled/main.cpp:23: candidate template ignored: requirement 'has_something_v<wrong_type>' was not satisfied [with T = wrong_type]



但是当我用另一个模板函数调用时:

template <typename ...T, typename = std::enable_if_t<has_something_v<T...>>>
void some_function(const T... args)
{
(some_function(args), ...);
}

void f ()
{
some_function(1, 2, a());
}

编译器给我一个非常糟糕的错误消息,因为我没有可接受的参数包特征:

Compiler error message

而且,如果我从上一个模板函数中删除了 std::enable_if,一切正常,直到我将 wrong_type类型发送给函数,导致程序崩溃。

对于参数包,我这样写:

template <typename ...T>
struct has_something
{
static bool value;

static constexpr bool c(T... args)
{
value = (args && ...);
return value;
}
};

template <>
struct has_something<int>
{
static constexpr bool value = true;
};

template <typename ...T>
const bool has_something_v = has_something<T...>::value;

但是它仍然失败。

我如何编写可接受的参数包类型特征?

最佳答案

如果要使特征接受参数包,并且仅当参数包具有单个类型且该类型为true时,其值为int,则只需对代码进行少量更改:

#include <iostream>
#include <type_traits>

template <typename...T>
struct has_something : std::false_type {};

template <>
struct has_something<int> : std::true_type {};

template <typename... T>
constexpr bool has_something_v = has_something<T...>::value;

int main() {
std::cout << has_something_v<int>;
std::cout << has_something_v<double>;
std::cout << has_something_v<int,double>;
}

使用 std::true_typestd::false_type使特征更短一些。我只需要使特征接受参数包,特化就可以保持不变。

最后但并非最不重要的一点是,您应该选择一个更好的名称。例如 is_one_int将比 something好得多。

PS:SFINAE可用于创建编译器错误,但通常,简单的 static_assert是获得清晰消息的更好选择:
template <typename...T>
void foo(T...args) {
static_assert( is_one_int_v<T...>, " put nice message here");
}

当您想消除不同的重载的歧义时,SFINAE是首选的工具,但是如果一个函数在没有替代方法的情况下应该失败,那么 static_assert会更简单。

关于c++ - 如何使特征接受参数包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62423360/

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