2014-03-01 140 views
1

這個小程序的std :: tuple_size和部分專門模板

https://ideone.com/dqVJbN

#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; 
} 

在GCC編譯很好,但產生一個「錯誤C2755: '元數據:: addVarDesc ::值,MSGT>' :部分專業化的非類型參數必須是在MS Visual Studio中一個簡單的標識符」 2013年

我在想,是什麼在這裏需要這種代碼的最小/最好的變化在2013年VS

工作

編輯試圖以不同的方式重新調整它:如何獲得元組大小作爲編譯時常量,有資格用作模板參數?

編輯基本上用integral_costant<int, ID>代替int ID解決了這個問題。

+1

此代碼看起來格式不正確的號碼,請參閱http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1315。您需要將'ID'作爲一個類型參數,並將'std :: tuple_size <...> :: value'包裝爲'int_ <...>'或'std :: integral_constant '。請參閱http://stackoverflow.com/questions/5978617/why-is-it-disallowed-for-partial-specialization-in-a-non-type-argument-to-use-ne –

+0

好吧,gcc不介意,並且考慮到標準合規性通常比微軟更好,我不認爲可能存在標準限制。你能寫一個答案,所以我可以將問題標記爲已解決? –

回答

1

我被要求創建一個答案。你需要用一個類型

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) 
    { 

    } 
}; 
1

儘管此代碼不符合標準,但您可以簡單地更改它。這裏是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; 
    } 
}; 

這兩種方法都可能是錯的,如果這樣的延期交貨(從最後到第一個元組元素)不適合你。但是可以修改它們來解釋這一點。