在编译时必须知道模板参数。如果你可以改变你的函数采取tag
作为模板参数,它会工作:
template <int tag, typename T>
void add_field(T value)
{
using t = typename tag_traits<tag>::type;
// more...
}
// ...
int main()
{
test t;
t.add_field<1>("");
t.add_field<2>("");
}
如果这不是一个选项,你需要一个switch
或类似的结构:
template <typename T>
void add_field(int tag, T value)
{
switch (tag) {
case 1:
{
using t = typename tag_traits<1>::type;
// more...
break;
}
case 2:
{
using t = typename tag_traits<2>::type;
// more...
break;
}
}
}
的问题是全部这些情况必须在语法上和语义上有效全部值T
。如果这是不是一种选择,要么,就需要有一个辅助特质重型机械模板:
template <int tag, class T>
struct is_acceptable : std::false_type
{};
template <int tag>
struct is_acceptable<tag, typename tag_traits<tag>::type> : std::true_type
{};
// Add any other specialisations as applicable
// ...
template <typename T>
void add_field(int tag, T value)
{
switch (tag) {
case 1:
{
add_field_helper<1, T>::call(value);
break;
}
case 2:
{
add_field_helper<2, T>::call(value);
break;
}
}
}
template <int tag, class T, bool acceptable = is_acceptable<tag, T>::value>
struct add_field_helper
{
static void call(T) {}
};
template <int tag, class T>
struct add_field_helper<tag, T, true>
{
static void call(T value)
{
using t = typename tag_traits<tag>::type;
// more...
}
};
空call
为is_acceptable
的false
值的存在只是为了避免编译错误,不正确的实例。假设你永远不会拨打add_field
与无效的tag
- T
组合,它永远不会在运行时调用。
如果有太多的标签用手几乎一一列举了,你可以使用Boost.Preprocessor生成它们。对于有效标记值0
... MAX_TAG - 1
,下面可以使用:
#define ONE_CASE(z, tag, unused) \
case tag: add_field_helper<tag, T>::call(value); break;
template <typename T>
void add_field(int tag, T value)
{
switch (tag) {
BOOST_PP_REPEAT(MAX_TAG, ONE_CASE, %%)
}
}
我没有使用正常传递到宏观,我通常使用句法废话%%
表示数据参数。如果你愿意,你可以传递和使用任何东西。
如果提升。预处理是太黑暗魔法给你,你也可以使用模板递归:
template <class T>
void add_field(int tag, T value)
{
add_field_dispatcher<0, T>::call(tag, value);
}
template <int one_tag, class T>
struct add_field_dispatcher
{
static void call(int tag, T value)
{
if (tag == one_tag) add_field_helper<one_tag, T>::call(value);
else add_field_dispatcher<one_tag + 1, T>::call(tag, value);
}
};
template <class T>
struct add_field_dispatcher<MAX_TAG, T>
{
static void call(int tag, T value)
{
// Called with unsupported tag
}
};
做任何事情,从使用阻止你't.add_field <1>(“”);'到位t.add_field的'(1,“ “);'? –
这是不可能的,因为在编译时标记是未知的。 – 0xBADF00
在编译时您需要模板参数,而add_field的参数在运行时给出。尝试解释目的是什么?可能有更合适的解决方案。 – Taus