gpt4 book ai didi

c++ - 带有模板包 : disabling member if no template arguments 的 SFINAE

转载 作者:太空狗 更新时间:2023-10-29 21:34:20 26 4
gpt4 key购买 nike

我想定义一个带有可选模板参数的类:

  • 如果参数存在并且它是一个枚举类,定义一个运算符()
  • 类可以在没有附加模板的情况下被实例化参数(在这种情况下 operator() 不存在)

目标是允许通过可选的枚举类访问数组元素。

代码:

#include <type_traits>

template <int N, typename... T>
class data {
int x[N];

template <typename T0, typename... T1>
struct enum_wrapper {
typedef T0 type;
};
public:

template <bool activate = (sizeof...(T) > 0)>
std::enable_if_t<activate, int>&
operator()(const typename enum_wrapper<T...>::type& e)
{ return x[static_cast<std::size_t>(e)]; }
};
int main()
{
data<3> a;
return 0;
}

enum_wrapper 的目的是挑出包中的第一个参数typename... T .

g++ -std=c++14编译的代码给出错误

error: wrong number of template arguments (0, should be at least 1)

关于 operator() 的定义。这是因为 enum_wrapper<T...>::type当使用单个参数对数据进行统计时未定义 <3> .但是,模板参数 bool activateoperator() 的定义中及其返回类型 std::enable_if_t<activate, int>旨在防止 operator() 的实例化当参数包typename... T是空的。为什么要定义operator() SFINAE下不是简单丢弃?

此外,我想在 enum_wrapper::type 时进一步消除 operator()不是 enum class , 使用 std::is_enum .条件如

std::enable_if<std::is_enum_v<(enum_wrapper<T...>::type)>>

应该插入以使 SFINAE 工作?

最佳答案

问题是 operator() 的参数类型不依赖于模板参数(到 operator() )

您可以通过间接指定一个必须与类相同的新参数包使其依赖(不幸的是,我们不能默认参数包,否则我们会)

template <bool activate = (sizeof...(T) > 0), typename... U>
std::enable_if_t<activate && std::conjunction_v<std::is_same<T, U>...>, int>&
operator()(const typename enum_wrapper<U...>::type& e)
{ return x[static_cast<std::size_t>(e)]; }

Demo


我想我有点担心你实际上打算如何调用 operator() , 自 enum_wrapper在类中是私有(private)的。我认为您真正感兴趣的是接收与 enum_wrapper<T...>::type 相同的类型.这里最简单的是简单地为 enum_wrapper 进行特化对于一个空的 T... , 然后禁用 operator()为此:

template<class...>
struct enum_wrapper{using type = int;};

template <typename T0, typename... T1>
struct enum_wrapper<T0, T1...> {
typedef T0 type;
};

//...

template <bool activate = (sizeof...(T) > 0)>
std::enable_if_t<activate, int>&
operator()(const typename enum_wrapper<T...>::type& e)
{ return x[static_cast<std::size_t>(e)]; }

然后我们可以这样调用它:

data<3> a; // no operator()

data<3, int> b; // operator() viable
b.x[0] = 1;
b.x[1] = 3;
b.x[2] = 5;
std::cout << b(1) << std::endl; // print '3'

Better Demo

(我创建了成员 x public 用于测试目的)


最后,将您的论点的条件简单地移动到 operator() 可能会更容易。类型为 enum_wrapper<T...>::type进入 static_assert在受您的 bool activate 保护的功能中:

template <class U, bool activate = (sizeof...(T) > 0)>
std::enable_if_t<activate, int>&
operator()(const U& e)
{
static_assert(std::is_same_v<U, typename enum_wrapper<T...>::type>, L"argument type to operator() is incorrect");
return x[static_cast<std::size_t>(e)];
}

你可以像之前那样调用,还是没有operator()a 定义.如果您尝试调用 b(2.0) ,但是,您会触发静态断言。

Best Demo

关于c++ - 带有模板包 : disabling member if no template arguments 的 SFINAE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46954648/

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