英文:
get the first with specific type in a variadic function
问题
这是我的第二篇帖子,我在发布之前尽力寻找了尽可能多的信息(包括使用ChatGPT的新可能性),以更好地理解可变参数函数的工作方式。第一次尝试成功,我检查了给定的参数列表是否包含特定类型的参数。
template<typename T, typename Arg>
auto hasType(Arg arg) -> bool {
return std::is_same<T, decltype(arg)>::value;
}
template <typename T, typename... Args>
auto hasType(Args... args) {
return (hasType<T>(args) || ...);
}
// 调用方式
std::string thisIsATest = "this is a test";
hasType<float>(thisIsATest, "Hello, world!", 5.67, 452);
现在下一步是获取第一个特定参数的值。我创建了两个新的可变参数方法:
// 如果没有找到特定类型,使用此回退方法
template<typename T>
auto getFirst() -> T {
throw someCustomException("参数列表不包含特定类型。");
}
template<typename T, typename Arg, typename... Args>
auto getFirst(Arg arg, Args... args) -> T {
// 测试如果arg的类型与T不同,就递归调用带有下一个参数的函数
if (!(std::is_same<T, decltype(arg)>::value)) {
return getFirst<T>(args...);
}
// arg现在应该满足与T匹配的条件
return arg;
}
调用getFirst的方式如下:
std::string thisIsATest = "This is a test";
std::string thisIsAnOtherString = "This is another string";
int intValue = 5;
double doubleValue = 28.563;
auto result = getFirst<std::string>(5, 1.2567, intValue, true, thisIsATest, doubleValue, false, 945.621, thisIsAnOtherString);
// result = thisIsATest
我尝试了一些更改,比如:
- 将getFirst的返回类型从T更改为Arg(调用"return getFirst
(args...);"时会出现其他错误) - 将第一个参数从值更改为引用 => 与示例中提供的相同错误
- 尝试将arg转换为类型T,但没有找到有效的方法
目前,我在可变参数主题中有些困惑,不确定要进行哪些必要更改以实现所需的功能,或者是否可以达到这个目标。也许有人可以在这里帮助我。
谢谢。
编辑:在我本地的代码中只有一个小变化,这个变化导致了无法正常工作的解决方案。
英文:
this is my 2nd post and i tried to find as much information before posting here as i could (including the new possibility with chatgpt) to understand some more the work of variadic function. The first try runs well where i checked if the given argument list includes a sepcific typ of argument.
template<typename T, typename Arg>
auto hasType(Arg arg) -> bool {
return std::is_same<T, decltype(arg)>::value;
}
template <typename T, typename... Args>
auto hasType(Args... args) {
return (hasType<T>(args) || ...);
}
// call like
std::string thisIsATest = "this is a test";
hasType<float>(thisIsATest, "Hello, world!", 5.67, 452);
Now the next step was getting the value of the first specific argument. I created 2 new variadic methods:
// The fall back if there is none of the specific type i search
template<typename T>
auto getFirst() -> T {
throw someCustomException("Argument list not including the specific type.");
}
template<typename T, typename Arg, typename... Args>
auto getFirst(Arg arg, Args... args) -> T {
// test if arg is not the same type and call recursive the function with
// next argument
if (!(std::is_same<T, decltype(arg)>::value)) {
return getFirst<T>(args...);
}
// the arg should now match the condition to match type with T
return arg;
//-----^--- Multiple Errors like : could not convert ‘arg’ from ‘int’ to ‘std::__cxx11::basic_string<char>’ Or error: could not convert ‘arg’ from ‘double’ to ‘std::__cxx11::basic_string<char>’
}
The idea is to call getFirst like that:
std::string thisIsATest = "This is a test";
std::string thisIsAnOtherString = "This is an other string";
int intValue = 5;
double doubleValue = 28.563;
auto result = getFirst<std::string>(5, 1.2567, intValue, true, thisIsATest, doubleValue, false, 945.621, thisIsAnOtherString);
// result = thisIsATest
There are some changes i tried, like:
- changing the return type of getFirst from T to Arg (other errors when calling "return getFirst<T>(args...);")
- changing first argument from value to reference => same errors provided in example
- trying to cast arg to type T but didn't found a working posibility
In the moment i'm a litle bit stucked in the hole variadic topic, where to make the necessary changes to reach the functionality or if this is reachable at all. Maybe someone can help me here.
Thanks.
Edit: There was just a little change in my local code which holds the solution from working correctly.
答案1
得分: 3
不要使用std::is_same
,使用另一个重载。
template<typename T>
T getFirst() // 递归基本情况
{
throw whatever();
}
template<typename T, typename... Args>
T getFirst(T& arg, Args... args) // 匹配情况
{
return arg;
}
template<typename T, typename Arg, typename... Args>
T getFirst(Arg arg, Args... args) // 继续搜索情况
{
return getFirst(args);
}
英文:
Instead of using std::is_same
, use another overload.
template<typename T>
T getFirst() // recursion base case
{
throw whatever();
}
template<typename T, typename... Args>
T getFirst(T& arg, Args... args) // matching case
{
return arg;
}
template<typename T, typename Arg, typename... Args>
T getFirst(Arg arg, Args... args) // continuing the search case
{
return getFirst(args);
}
答案2
得分: 3
auto
返回类型推断要求从不同的 return
语句中推断出的类型匹配。你的代码没有匹配。你可以使用 if constexpr
来丢弃 false 分支,然后就没有关于返回类型的问题:
template<typename T, typename Arg, typename... Args>
auto getFirst(Arg arg, Args... args) -> T {
if constexpr (!(std::is_same<T, decltype(arg)>::value)) {
return getFirst<T>(args...);
} else {
return arg;
}
}
英文:
auto
return type deduction requires the type deduced from different return
statements to match. Yours don't. You use if constexpr
to have the false branch discarded, then there is no issue with deducing the return type:
template<typename T, typename Arg, typename... Args>
auto getFirst(Arg arg, Args... args) -> T {
if constexpr (!(std::is_same<T, decltype(arg)>::value)) {
return getFirst<T>(args...);
} else {
return arg;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论