如何解决根据 std::tuple 的大小更改函数的返回类型
问题
以下是我面临的一个问题的简化、人为示例。本质上,我需要一个可以容纳任意数量项目的对象,并在需要时返回这些项目。
template<typename... Ts>
class Foo {
public:
Foo(Ts... args) :
mArgs{std::forward<Ts>(args)} {
}
std::tuple<Ts...> getArgs() const {
return mArgs;
}
private:
std::tuple<Ts...> mArgs;
};
这在 args > 1 时工作正常。
Foo<int,int> f{1,2};
auto result = f.getArgs(); // result is a tuple containing two ints.
但是,如果 args == 1,我宁愿不从 getArgs
中获取元组。
Foo<int> f{1};
auto result = f.getArgs(); // result is a tuple,but I want it to be an int.
问题
有没有办法,也许使用 SFINAE,定义另一个 getArgs
函数,当 args == 1 时使用?类似于(这显然是非常错误的):
template<typename = std::enable_if_t<std::tuple_size_v<Ts...> == 1>>
??? getArgs() const {
return mArgs;
}
这有几个明显的问题:
- 我不确定
std::tuple_size_v<Ts...>
是否会起作用。 - 我不知道新的返回类型是什么。或许
std::tuple_element
在这里会有用。
解决方法
另一种方法:使用 sizeof...(T) == 1
来确定是否只有一种类型在使用。然后使用 auto
返回类型和 if constexpr
来完成剩下的工作。
template<typename... T>
class Foo {
public:
Foo(T&&... t)
: mArgs{std::forward<T>(t)...} {
}
auto getArgs() const {
if constexpr (sizeof...(T) == 1) {
return std::get<0>(mArgs);
} else {
return mArgs;
}
}
private:
std::tuple<T...> mArgs;
};
示例用法:
auto foo_i = Foo{11};
auto foo_c = Foo{'c'};
auto foo_ic = Foo{11,'c'};
int i2 = foo_i.getArgs();
char c2 = foo_c.getArgs();
std::tuple<int,char> ic2 = foo_ic.getArgs();
,
您实际上可以通过对给定类型集的部分特化来做到这一点。不需要 SFINAE。以下是使用 int
示例的方法:
#include <stdio.h>
#include <tuple>
template<typename... Ts>
struct storage {
typedef std::tuple<Ts...> type;
};
template<typename T>
struct storage<T> {
typedef T type;
};
template<typename... Ts>
class Foo {
public:
Foo(Ts... args) :
mArgs{std::forward<Ts>(args)...} {
}
typename storage<Ts...>::type getArgs() const {
return mArgs;
}
private:
typename storage<Ts...>::type mArgs;
};
int main(int argc,char **argv)
{
Foo<int,int> f1{1,2};
Foo<int> f2{1};
std::tuple<int,int> args1 = f1.getArgs();
printf("args1 = (%d,%d)\n",std::get<0>(args1),std::get<1>(args1));
int args2 = f2.getArgs();
printf("args2 = %d\n",args2);
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。