gpt4 book ai didi

c++ - SFINAE:函数模板优化

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:34:51 25 4
gpt4 key购买 nike

我想用成员函数模板以某种方式迭代一个元组(以便稍后从给定的模板类型 T 创建一个新类型的元组)。

但是,没有使用中断条件(函数)所以我得到这个错误:

invalid use of incomplete type: 'class std::tuple_element<0ul, std::tuple<> >'

问题似乎是,即使 N == size 的元组,std::tuple_element_t 也被评估为 N != size 并且不作为 SFINAE 处理。

两个示例都显示了不同的无效解决方案。我做错了什么?

注意:省略了使用 is_same 评估的函数以最小化示例。

#include <type_traits>
#include <tuple>

template<typename...Ts>
struct A
{
using tuple = std::tuple<Ts...>;
static constexpr std::size_t size = sizeof...(Ts);

template<typename T, std::size_t N = 0, typename std::enable_if_t<N == size>* = nullptr>
int get()
{
return 0;
}

template<typename T, std::size_t N = 0, typename std::enable_if_t<N != size && !std::is_same<T, std::tuple_element_t<N, tuple>>::value>* = nullptr>
int get()
{
return get<T, N + 1>() - 1;
}
};

int main()
{
A<int, float, double, float, float> a;

return a.get<char>();
}

Live Example 1

#include <type_traits>
#include <tuple>

template<typename...Ts>
struct A
{
using tuple = std::tuple<Ts...>;
static constexpr std::size_t size = sizeof...(Ts);

template<typename T, std::size_t N = 0>
std::enable_if_t<N == size, int> get()
{
return 0;
}

template<typename T, std::size_t N = 0>
std::enable_if_t<N != size && !std::is_same<T, std::tuple_element_t<N, tuple>>::value, int> get()
{
return get<T, N + 1>() - 1;
}
};

int main()
{
A<int, float, double, float, float> a;

return a.get<char>();
}

Live Example 2

一种变通方法是使用第三个函数来评估 sizeof tuple - 2,然后评估 sizeof tuple - 1,但这真的有必要吗?

#include <type_traits>
#include <tuple>

template<typename...Ts>
struct A
{
using tuple = std::tuple<Ts...>;
static constexpr std::size_t size = sizeof...(Ts);

template<typename T, std::size_t N = 0, typename std::enable_if_t<(N == size - 1) && std::is_same<T, std::tuple_element_t<N, tuple>>::value>* = nullptr>
int get()
{
return 1;
}

template<typename T, std::size_t N = 0, typename std::enable_if_t<(N == size - 1) && !std::is_same<T, std::tuple_element_t<N, tuple>>::value>* = nullptr>
int get()
{
return 2;
}

template<typename T, std::size_t N = 0, typename std::enable_if_t<(N < size - 1) && !std::is_same<T, std::tuple_element_t<N, tuple>>::value>* = nullptr>
int get()
{
return get<T, N + 1>() - 1;
}
};

int main()
{
A<int, float, double, float, float> a;

return a.get<char>();
}

Live Example 3

最佳答案

正如@PiotrSkotnicki 在对问题的评论中所建议的,这里是你的第二个例子,一旦修复:

#include <type_traits>
#include <tuple>

template<typename...Ts>
struct A
{
using tuple = std::tuple<Ts...>;
static constexpr std::size_t size = sizeof...(Ts);

template<typename T, std::size_t N = 0>
std::enable_if_t<N == size-1, int>
get()
{
return std::is_same<T, std::tuple_element_t<N, tuple>>::value ? N : 0;
}

template<typename T, std::size_t N = 0>
std::enable_if_t<N != size-1 && !std::is_same<T, std::tuple_element_t<N, tuple>>::value, int>
get()
{
return get<T, N + 1>() - 1;
}
};

int main()
{
A<int, float, double, float, float> a;
return a.get<char>();
}

问题是什么?
考虑以下行:

std::enable_if_t<N != size && !std::is_same<T, std::tuple_element_t<N, tuple>>::value, int> get() 

在这种情况下,N 被替换以评估 enable_if 的条件,即使 N == size(替换是必须找到确实 N == size)。
因此,tuple_element_t(让我说)发出了一个超出范围的错误,这就是你得到编译错误的原因。

我只是更新了您的代码,以避免在遍历 N 时达到 size。这是一个使用 size-1 作为在函数之间切换的值的问题。

关于c++ - SFINAE:函数模板优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39492632/

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