我有下一条命令:
auto result = Builder::get(
ObjKey("key1"),
ObjVal("test1"),
(ObjKey("key2"), ObjVal("test21"), (ObjKey("key3"), ObjVal("test31"), ObjVal("test32")), ObjVal("test22")),
ObjVal("test2")
);
我希望得到以下结果:
{key1, test1, {key2, test21, {key3, test31, test32}, test22}, test2}
但是我得到这个结果:
{key1, test1, test22, test2}
程序代码如下(标准11):
#include <iostream>
class ObjKey {
public:
ObjKey() = delete;
ObjKey(const std::string& key) : m_key(key) { }
std::string get() const {
return m_key + ", ";
}
private:
std::string m_key;
};
class ObjVal {
public:
ObjVal() = delete;
ObjVal(const std::string& value) : m_value(value) { }
std::string get() const {
return m_value + ", ";
}
private:
std::string m_value;
};
class Builder {
public:
template<typename... Args>
static std::string get(ObjKey&& objKey, Args&& ...args) {
std::string resultValue;
get(resultValue, std::forward<ObjKey>(objKey), std::forward<Args>(args)...);
return resultValue;
}
private:
Builder() {}
template<typename... Args>
static void get(std::string& resultValue, ObjKey&& objKey, Args&& ...args) {
resultValue.append("{");
resultValue.append(objKey.get());
std::string values;
get(values, std::forward<Args>(args)...);
resultValue.append(values);
resultValue.append("}");
}
template<typename... Args>
static void get(std::string& resultValue, ObjVal&& objVal, Args&& ...args) {
resultValue.append(objVal.get());
get(resultValue, std::forward<Args>(args)...);
}
static void get(std::string& resultValue) {}
};
int main()
{
auto result = Builder::get(
ObjKey("key1"),
ObjVal("test1"),
(ObjKey("key2"), ObjVal("test21"), (ObjKey("key3"), ObjVal("test31"), ObjVal("test32")), ObjVal("test22")),
ObjVal("test2")
);
std::cout << result << "\n";
}
我在做什么错了?
有可能用模板求解吗?
答案 0 :(得分:0)
我在做什么错了?
n.m。建议,您必须考虑逗号运算符对以下表达式的作用
(ObjKey("key2"), ObjVal("test21"), (ObjKey("key3"), ObjVal("test31"), ObjVal("test32")), ObjVal("test22"))
逗号运算符会丢弃除最后一个值以外的所有值,因此表达式变为
(ObjVal("test22"))
有可能用模板求解吗?
是的,但是我能想到的最好的是std::tuple
。
我的意思是...如果您接受get()
通话成为
auto result = Builder::get(
ObjKey("key1"),
ObjVal("test1"),
std::make_tuple(ObjKey("key2"), ObjVal("test21"),
std::make_tuple(ObjKey("key3"), ObjVal("test31"),
ObjVal("test32")),
ObjVal("test22")),
ObjVal("test2"));
因此,在分组std::make_tuple
之前加上(
,您可以添加几个私有get()
来管理元组大小写。
因此,将getH()
的私有版本重命名为get()
(用于“获取帮助者”),可以将getH()
的元组管理版本编写为(C ++ 14解决方案,因为使用std::index_sequence
和std::make_index_sequence
;但是如果您需要C ++ 11解决方案,编写C ++ 11替代品并不难)
template <std::size_t ... Is, typename ... Ts, typename ... As>
static void getH (std::string & rV, std::index_sequence<Is...> const &,
std::tuple<Ts...> const t, As ... as)
{
getH(rV.append(", "), std::get<Is>(t)...);
getH(rV, as...);
}
template <typename ... Ts, typename ... As>
static void getH (std::string & rV, std::tuple<ObjKey, Ts...> const t,
As ... as)
{ getH(rV, std::make_index_sequence<1u+sizeof...(Ts)>{}, t, as...); }
键和值版本的管理如下
template <typename ... As>
static void getH (std::string & rV, ObjKey const & oK, As ... as)
{
getH(rV.append(1u, '{').append(oK.get()), as...);
rV.append(1u, '}');
}
template <typename ... As>
static void getH (std::string & rV, ObjVal const & oV, As ... as)
{ getH(rV.append(", ").append(oV.get()), as...); }
很明显是地面案例
static void getH (std::string &)
{ }
get()
公开版本变为
template <typename ... As>
static std::string get (As ... as)
{
std::string resultValue;
getH(resultValue, as...);
return resultValue;
}
请注意,我已经将逗号的管理从ObjKey
和ObjVal
转移到getH()
,并且我删除了转发语义(您从未使用过std::move
)。
以下是完整的C ++ 14示例
#include <tuple>
#include <iostream>
class Obj
{
public:
Obj() = delete;
Obj (std::string const & v0) : v{v0}
{ }
std::string const & get () const
{ return v; }
private:
std::string v;
};
struct ObjKey : public Obj
{ ObjKey (std::string const & v0) : Obj{v0} { } };
struct ObjVal : public Obj
{ ObjVal (std::string const & v0) : Obj{v0} { } };
class Builder
{
private:
template <std::size_t ... Is, typename ... Ts, typename ... As>
static void getH (std::string & rV, std::index_sequence<Is...> const &,
std::tuple<Ts...> const t, As ... as)
{
getH(rV.append(", "), std::get<Is>(t)...);
getH(rV, as...);
}
template <typename ... Ts, typename ... As>
static void getH (std::string & rV, std::tuple<ObjKey, Ts...> const t,
As ... as)
{ getH(rV, std::make_index_sequence<1u+sizeof...(Ts)>{}, t, as...); }
template <typename ... As>
static void getH (std::string & rV, ObjKey const & oK, As ... as)
{
getH(rV.append(1u, '{').append(oK.get()), as...);
rV.append(1u, '}');
}
template <typename ... As>
static void getH (std::string & rV, ObjVal const & oV, As ... as)
{ getH(rV.append(", ").append(oV.get()), as...); }
static void getH (std::string &)
{ }
public:
template <typename ... As>
static std::string get (As ... as)
{
std::string resultValue;
getH(resultValue, as...);
return resultValue;
}
};
int main()
{
auto result = Builder::get(
ObjKey("key1"),
ObjVal("test1"),
std::make_tuple(ObjKey("key2"), ObjVal("test21"),
std::make_tuple(ObjKey("key3"), ObjVal("test31"),
ObjVal("test32")),
ObjVal("test22")),
ObjVal("test2"));
std::cout << result << "\n";
}