在編譯時必須知道模板參數。如果你可以改變你的函數採取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