![](/img/trans.png)
[英]C++: Can std::tuple_size/tuple_element be specialized?
[英]std::tuple_size and partially specialized templates
这个小程序
#include <iostream>
#include <tuple>
#include <string>
using namespace std;
class MetaData
{
public:
template<int ID, class T>
void addVar(string varNames)
{
// do smth
}
template<int ID, class MSGT>
struct addVarDesc
{
static void exec(MetaData& md, string varNames)
{
typedef typename std::tuple_element<ID, typename MSGT::values_type>::type varType;
md.addVar<ID, varType>(varNames);
addVarDesc<ID+1, MSGT>::exec(md, varNames);
}
};
template<class MSGT>
struct addVarDesc<std::tuple_size<typename MSGT::values_type>::value, MSGT>
{
static void exec(MetaData& md, string varNames)
{
}
};
template<class MSGT>
static MetaData createMetaData(string varNames)
{
MetaData md;
MetaData::addVarDesc<0, MSGT>::exec(md, varNames);
return md;
}
};
template<typename... Types>
class Message
{
public:
tuple<Types...> m_values;
typedef tuple<Types...> values_type;
static MetaData m_meta;
};
typedef Message<string, double> MyMessageType;
template<>
MetaData MyMessageType::m_meta = MetaData::createMetaData<MyMessageType>("name\nmass");
int main() {
// your code goes here
return 0;
}
在Microsoft Visual Studio 2013中,在gcc中编译良好,但产生了“错误C2755:'MetaData :: addVarDesc :: value,MSGT>':部分专业化的非类型参数必须是简单的标识符”。
我想知道,此代码在VS 2013中工作所需的最小/最佳更改是什么?
编辑尝试以不同的方式改写它:如何获取元组大小作为编译时常数,可以用作模板参数?
编辑基本上,使用integral_costant<int, ID>
代替int ID
解决了此问题。
尽管此代码不符合标准,但是您可以很简单地对其进行更改。 这是MetaData
类的修改版本:
class MetaData
{
public:
template<int ID, class T>
void addVar(string varNames)
{
// do smth
}
template<class MSGT, int ID = std::tuple_size<typename MSGT::values_type>::value - 1>
struct addVarDesc
{
static void exec(MetaData& md, string varNames)
{
typedef typename std::tuple_element<ID, typename MSGT::values_type>::type varType;
md.addVar<ID, varType>(varNames);
addVarDesc<MSGT, ID-1>::exec(md, varNames);
}
};
template<class MSGT>
struct addVarDesc<MSGT, 0>
{
static void exec(MetaData& md, string varNames)
{
}
};
template<class MSGT>
static MetaData createMetaData(string varNames)
{
MetaData md;
MetaData::addVarDesc<MSGT>::exec(md, varNames);
return md;
}
};
也可以用另一种方法解决此问题-使用围绕MetaData::addVarDesc::exec
方法的包装器:
class MetaData
{
public:
template<int ID, class T>
void addVar(string varNames)
{
// do smth
}
template<int ID, class MSGT>
struct addVarDescImpl
{
static void exec(MetaData& md, string varNames)
{
typedef typename std::tuple_element<ID, typename MSGT::values_type>::type varType;
md.addVar<ID, varType>(varNames);
addVarDescImpl<ID-1, MSGT>::exec(md, varNames);
}
};
template<class MSGT>
struct addVarDescImpl<0, MSGT>
{
static void exec(MetaData& md, string varNames)
{
}
};
template<class MSGT>
static void addVarDesc(MetaData& md, string varNames)
{
addVarDescImpl<std::tuple_size<typename MSGT::values_type>::value - 1, MSGT>::exec(md, varNames);
}
template<class MSGT>
static MetaData createMetaData(string varNames)
{
MetaData md;
addVarDesc<MSGT>(md, varNames);
return md;
}
};
如果这种延迟顺序(从最后一个到第一个元组元素)不适合您,则这两种方法都可能是错误的。 但是可以对其进行修改以解决此问题。
我被要求创造一个答案。 您需要将数字包装成一个类型
template<typename ID, class MSGT>
struct addVarDescImpl;
template<int ID, class MSGT>
struct addVarDesc : addVarDescImpl<std::integral_constant<int, ID>, MSGT>
{};
template<typename ID, class MSGT>
struct addVarDescImpl
{
static void exec(MetaData& md, string varNames)
{
typedef typename std::tuple_element<ID::value, typename MSGT::values_type>::type varType;
md.addVar<ID::value, varType>(varNames);
addVarDesc<ID::value+1, MSGT>::exec(md, varNames);
}
};
template<class MSGT>
struct addVarDescImpl<
std::integral_constant<int, std::tuple_size<typename MSGT::values_type>::value>,
MSGT>
{
static void exec(MetaData& md, string varNames)
{
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.