2017-03-15 123 views
2

這裏是什麼,我想實現一個正在運行的例子:使用非專業化的模板類型作爲模板參數

#include <iostream> 
#include <string> 
#include <typeinfo> 

template <class T> 
struct print 
{ 
    static void function(T thing) 
    { 
     std::cout << thing << std::endl; 
    } 
}; 

template <class T> 
struct printMore 
{ 
    static void function(T thing) 
    { 
     std::cout << thing << " and more" << std::endl; 
    } 
}; 

struct dynamicBase 
{ 
    const char* m_value; 

    size_t getType() 
    { 
     switch(*m_value) 
     { 
     case '0': //the string is going to be a small script, the type returned is known during execution but not at compile time 
      return typeid(int).hash_code(); 
     case '1': 
      return typeid(float).hash_code(); 
     } 
     return typeid(const char*).hash_code(); 
    } 

    template<class T> 
    T* tryGetValue() 
    { 
     if(getType() == typeid(T).hash_code()) 
      return (T*) (&(m_value[1])); //dumb example, actually I'll evaluate the string as script and return a value based on that 
     else 
      return nullptr; 
    } 

    void applyPrint() 
    { 
     if(int* t = tryGetValue<int>()) 
      print<int>::function(*t); //I can cout an int so this line compile 
     else if(float* t = tryGetValue<float>()) 
      print<float>::function(*t); //I can cout a float so this one too 
     else 
      print<const char*>::function(*tryGetValue<const char*>()); //same 
    } 
    void applyPrintMore() 
    { 
     if(int* t = tryGetValue<int>()) 
      printMore<int>::function(*t); 
     else if(float* t = tryGetValue<float>()) 
      printMore<float>::function(*t); 
     else 
      printMore<const char*>::function(*tryGetValue<const char*>()); //same 
    } 

    //.... applyprintPretty, applyprintInRed, applyprintInBlue, ..... 
}; 

int main() 
{ 
    dynamicBase d; 
    d.m_value = "0a\0\0\0"; 
    d.applyPrint(); //97 == ascii value of 'a' 

    __asm {nop}; //for breakpoint purpose 
} 

起初,我以爲我可以用這樣的一個模板:

template<class myFunctionClass> 
    void applyPrint() 
    { 
     if(int* t = tryGetValue<int>()) 
      myFunctionClass<int>::function(*t); 
     else if(float* t = tryGetValue<float>()) 
      myFunctionClass<float>::function(*t); 
     else 
      myFunctionClass<const char*>::function(*tryGetValue<const char*>()); 
    } 

然後意識到我的錯誤(模板化的類型不是類型,直到你給他們模板參數)。但有沒有辦法重構這段代碼,所以我沒有15個applyStuff函數? (?我做錯了,我不能)

+0

'typeid()。hash_code'使我的眼睛流血。最終,這注定是[在dailywtf.com上的專題文章](http://thedailywtf.com/articles/You-Cant-Handle-the-True!) –

+0

生產代碼中沒有typeids。我們有我們自己的類型元信息。每個人都應該明白這是關於什麼,而不用擔心在運行時如何識別類型 – Nyashes

回答

4

您正在尋找模板模板參數

template<template <typename> class myFunctionClass> 
void applyPrint() 
{ 
     if(int* t = tryGetValue<int>()) 
      myFunctionClass<int>::function(*t); 
     else if(float* t = tryGetValue<float>()) 
      myFunctionClass<float>::function(*t); 
     else 
      myFunctionClass<const char*>::function(*tryGetValue<const char*>()); 
} 

你可以找到一個參考here: "cppreference.com - Template template parameters"

3

模板模板參數就是答案。

template<template <typename> class myFunctionClass> 
void apply() 
{ 
    if(int* t = tryGetValue<int>()) 
     myFunctionClass<int>::function(*t); 
    else if(float* t = tryGetValue<float>()) 
     myFunctionClass<float>::function(*t); 
    else 
     myFunctionClass<const char*>::function(*tryGetValue<const char*>()); 
} 

// ... 

apply<print>(); 
apply<printMore>(); 

沒有充分的理由,讓他們總是說「下課」,而不是「類型名稱」(儘管C++ 17個修復了這個)。內部參數集(這裏是bare關鍵字typename)的數量和種類必須與模板使用的參數數量相同,儘管它們不需要賦予名稱。