使用模板化方法处理意外行为
char unexpected behaviour with templated methods
我正在研究一个应该(因为它的硬件)由可变参数模板解决的问题。我缺乏理解使我无法解决以下错误。
密码是:
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
template<typename ... TL>
class LazySplitResult
{
public:
LazySplitResult(TL ...pl) :storedParams(pl ...) { }
void doStuff()
{
// invoke method with inside parameters
useStoredTuple(storedParams, std::index_sequence_for<TL...>());
}
template<typename T, typename T1, typename... Targs>
void doInsideLogic(T&& value1, Targs&& ... Fargs)
{
// there is some logic
// for example this
std::stringstream convert("0");
// it works for string,double,int ... other types are not supported
// so exception would be in place
convert >> value1;
}
void doInsideLogic()
{
}
private:
template<std::size_t... Is>
void useStoredTuple(const std::tuple<TL ...>& tuple,std::index_sequence<Is...>) {
wrapInsideLogic(std::get<Is>(tuple) ...);
}
void wrapInsideLogic(TL && ... args)
{
doInsideLogic(args...);
}
std::tuple<TL ...> storedParams;
};
template<typename ...TL>
LazySplitResult<TL ...> getResult(TL && ...pl)
{
return LazySplitResult<TL...>(pl ...);
}
int main()
{
std::string x;
int y;
double z;
// prepares an object
auto lazyResult=getResult(x, '.', '-', y, 'x', z , 'a');
// let it do its thing and set unset variables
lazyResult.doStuff();
std::cout << "x = " << x << ", y = " << y << ", z = " << z << std::endl;
return 0;
}
错误信息在这里
error C2664: 'void LazySplitResult<std::string &,char,char,int &,char,double &,char>::wrapInsideLogic(std::string &,char &&,char &&,int &,char &&,double &,char &&)': cannot convert argument 2 from 'const char' to 'char &&'
source_file.cpp(40): note: Conversion loses qualifiers
source_file.cpp(18): note: see reference to function template instantiation 'void LazySplitResult<std::string &,char,char,int &,char,double &,char>::useStoredTuple<0,1,2,3,4,5,6>(const std::tuple<std::string &,char,char,int &,char,double &,char> &,std::integer_sequence<_Ty,0,1,2,3,4,5,6>)'
复制自rextester here。
HW 的主要部分是解析公式并将结果保存在变量中,如下所示:
// declare variables and initialize class with formula
parse(x, '.', '-', y, 'x', z , 'a');
std::cout << "x = " << x << ", y = " << y << ", z = " << z << std::endl;
代码做同样的事情,只是它以惰性方式执行,因此需要将参数存储在元组中供以后使用。
我尝试实现相同的逻辑,除了懒惰,没有使用元组,class 成功了。可以观察here。没有出现错误描述转换错误。
你能帮帮我吗?我完全迷路了。入口方法调用是相同的,处理参数的可变参数模板方法具有相同的参数...唯一的区别似乎是元组和class inbetween.
不确定...您寻求帮助是针对第一个 link 引用的代码还是第二个 link 引用的代码?
我想是第二个代码,所以我建议按如下方式重新排序函数的定义。
首先是递归的基本情况
void myFunc ()
{ std::cout << "end" << std::endl; }
二、myFunc()
的递归版本
template <typename T, typename ... Targs>
void myFunc (T && value1, Targs && ... Fargs)
{
// there should be additional logic
// if value1 is char then skip it. But it was intentionally ommited
std::cout << " do" << std::endl;
const char* parsedValue = "0";
std::stringstream convert(parsedValue);
// cast current value according to thing.
convert >> value1;
myFunc(Fargs ...);
}
三、test()
template <typename ... Targs>
void test (Targs && ... args)
{ myFunc(args...); }
现在您的代码应该可以编译了。
如果您先写 test()
,然后写递归 myFunc()
,最后写基本情况 myFunc()
,那么 (1) test()
调用 myFunc()
when 未声明和 (2) 递归 myFunc()
调用基本情况 myFunc()
when 未声明。
首先,您的 doInsideLogic
函数模板中有一个无用的模板参数 T1
。删除它。
wrapInsideLogic
的参数不是转发引用,因为 TL
是已知的且未推导。它的参数 std::get<Is>(tuple)
是 const TL&
类型,因为 tuple
是 const std::tuple<TL...>&
类型,因此与参数类型 TL&&
不匹配。要解决此问题,有两种选择:
使用转发引用,即
template <typename... Targs>
void wrapInsideLogic(Targs&&... args)
{
doInsideLogic(std::forward<Targs>(args)...);
}
使用常量引用,即
void wrapInsideLogic(const TL&... args)
{
doInsideLogic(args...);
}
我正在研究一个应该(因为它的硬件)由可变参数模板解决的问题。我缺乏理解使我无法解决以下错误。
密码是:
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
template<typename ... TL>
class LazySplitResult
{
public:
LazySplitResult(TL ...pl) :storedParams(pl ...) { }
void doStuff()
{
// invoke method with inside parameters
useStoredTuple(storedParams, std::index_sequence_for<TL...>());
}
template<typename T, typename T1, typename... Targs>
void doInsideLogic(T&& value1, Targs&& ... Fargs)
{
// there is some logic
// for example this
std::stringstream convert("0");
// it works for string,double,int ... other types are not supported
// so exception would be in place
convert >> value1;
}
void doInsideLogic()
{
}
private:
template<std::size_t... Is>
void useStoredTuple(const std::tuple<TL ...>& tuple,std::index_sequence<Is...>) {
wrapInsideLogic(std::get<Is>(tuple) ...);
}
void wrapInsideLogic(TL && ... args)
{
doInsideLogic(args...);
}
std::tuple<TL ...> storedParams;
};
template<typename ...TL>
LazySplitResult<TL ...> getResult(TL && ...pl)
{
return LazySplitResult<TL...>(pl ...);
}
int main()
{
std::string x;
int y;
double z;
// prepares an object
auto lazyResult=getResult(x, '.', '-', y, 'x', z , 'a');
// let it do its thing and set unset variables
lazyResult.doStuff();
std::cout << "x = " << x << ", y = " << y << ", z = " << z << std::endl;
return 0;
}
错误信息在这里
error C2664: 'void LazySplitResult<std::string &,char,char,int &,char,double &,char>::wrapInsideLogic(std::string &,char &&,char &&,int &,char &&,double &,char &&)': cannot convert argument 2 from 'const char' to 'char &&'
source_file.cpp(40): note: Conversion loses qualifiers
source_file.cpp(18): note: see reference to function template instantiation 'void LazySplitResult<std::string &,char,char,int &,char,double &,char>::useStoredTuple<0,1,2,3,4,5,6>(const std::tuple<std::string &,char,char,int &,char,double &,char> &,std::integer_sequence<_Ty,0,1,2,3,4,5,6>)'
复制自rextester here。
HW 的主要部分是解析公式并将结果保存在变量中,如下所示:
// declare variables and initialize class with formula
parse(x, '.', '-', y, 'x', z , 'a');
std::cout << "x = " << x << ", y = " << y << ", z = " << z << std::endl;
代码做同样的事情,只是它以惰性方式执行,因此需要将参数存储在元组中供以后使用。
我尝试实现相同的逻辑,除了懒惰,没有使用元组,class 成功了。可以观察here。没有出现错误描述转换错误。
你能帮帮我吗?我完全迷路了。入口方法调用是相同的,处理参数的可变参数模板方法具有相同的参数...唯一的区别似乎是元组和class inbetween.
不确定...您寻求帮助是针对第一个 link 引用的代码还是第二个 link 引用的代码?
我想是第二个代码,所以我建议按如下方式重新排序函数的定义。
首先是递归的基本情况
void myFunc ()
{ std::cout << "end" << std::endl; }
二、myFunc()
的递归版本
template <typename T, typename ... Targs>
void myFunc (T && value1, Targs && ... Fargs)
{
// there should be additional logic
// if value1 is char then skip it. But it was intentionally ommited
std::cout << " do" << std::endl;
const char* parsedValue = "0";
std::stringstream convert(parsedValue);
// cast current value according to thing.
convert >> value1;
myFunc(Fargs ...);
}
三、test()
template <typename ... Targs>
void test (Targs && ... args)
{ myFunc(args...); }
现在您的代码应该可以编译了。
如果您先写 test()
,然后写递归 myFunc()
,最后写基本情况 myFunc()
,那么 (1) test()
调用 myFunc()
when 未声明和 (2) 递归 myFunc()
调用基本情况 myFunc()
when 未声明。
首先,您的 doInsideLogic
函数模板中有一个无用的模板参数 T1
。删除它。
wrapInsideLogic
的参数不是转发引用,因为 TL
是已知的且未推导。它的参数 std::get<Is>(tuple)
是 const TL&
类型,因为 tuple
是 const std::tuple<TL...>&
类型,因此与参数类型 TL&&
不匹配。要解决此问题,有两种选择:
使用转发引用,即
template <typename... Targs> void wrapInsideLogic(Targs&&... args) { doInsideLogic(std::forward<Targs>(args)...); }
使用常量引用,即
void wrapInsideLogic(const TL&... args) { doInsideLogic(args...); }