2015-02-23 221 views
0

我有很多的班級,不同的成員,所有這一切有我,詢問如何建立通用模板來執行這些操作如下類型C++模板變量類型聲明

::basedata::Maindata maindata; 
::basedata::Subdata subinfo("This goes into the subinfo vector"); 
subinfo.contexts(contextInfo); 
maindata.subdata().push_back(subinfo); 

注意的操作。我無法爲每種類型的maindata和subinfo設置一個特例。我也需要能夠看到如何從我的主代碼中調用模板。如果 maindata.subdata()存在,但我一直能夠建立一個模板,但如果它不存在,則在對該模板的調用中保持編譯失敗。那就是創建表格的模板

perform_Push(maindata.subdata(), subinfo); 

這樣就可以編譯maindata.subdata()是否存在。

我可以接受,建立模板,使主代碼可以顯示

bool retval 
retval = hasmember(maindata, subdata); 
if (retval) 
    { 
    buildmember(maindata.subdata, subinfo); 
    setAttributes(subinfo, data); 
    perform_Push(maindata.subdata(), subinfo) 
    } 
else 
    { 
    // Perform alternate processing 
    } 

截至目前,內如果不編譯代碼時被調用模板應該僅僅是無效的。

While :: basedata :: Maindata總是被定義的,:: basesata :: Subdata可能會或可能不會被定義,這取決於我的代碼正在使用的庫的版本。子數據被定義爲屬於maindata的矢量,因此它具有定義的push_back()操作。在任何情況下,都有太多類型的subData爲模板中的每個類型創建一個單獨的模板作爲T :: Subdata。

也就是說,如果子數據是唯一的情況下,我可以創建模板T的專業化爲:: maindata ::子數據和通用模板T.

我沒有包含文件的任何控制或庫,這樣我就不能創建一個變量的#define來用預編譯器進行測試。有沒有一種設置模板的好方法,可以讓它起作用?我可以使用返回布爾型true(成功)或false(無此類定義)的模板,並在運行時調用備用處理。我不需要有替代模板。

基本上,我問的是如何將SFINAE應用於這種特殊情況。

我設法找出我需要做的設置基本模板

如果我有最基本的操作

maindata.subdata().push_back(data) 

我可以定義表單模板,

<template class T, typename D> 
auto doPush(D data) -> decltype(T.pushback(data), void()) 
{ 
    T.push_back(data); 
} 

和通話將

doPush<maindata.subdata()>(data); 

但是,問題將是如何設置時,maindata還沒有成員的子數據。

+0

看一看型性狀和SFINAE – OMGtechy 2015-02-23 18:36:36

+0

我不知道你問:也許http://stackoverflow.com/questions/18701798/building-and-accessing-a-list-of -types-at-compile-time/18704609#18704609 – 2015-02-23 18:43:49

+0

@DieterLücking我會看看問題和答案,看看它是否可以提供幫助。 – sabbahillel 2015-02-23 18:55:38

回答

1

您可以使用此模板來獲取布爾值,告訴您是否存在Subdata類型的普通類型T。這隻在T是一個結構/類而不是名稱空間時纔有效。

#include <type_traits> 

template <class T, class V = void> 
    struct hasSubdata 
    { 
    enum { value = false }; 
    }; 

template <class T> 
    struct hasSubdata<T, typename std::enable_if< std::is_same<typename T::Subdata, typename T::Subdata>::value >::type> 
    { 
    enum { value = true }; 
    }; 


struct basedata1 
{ 
    struct Subdata {}; 
}; 

struct basedata2 
{ 

}; 

#include <iostream> 

int main() 
{ 
    std::cout << "basedata1: " << hasSubdata<basedata1>::value << std::endl; 
    std::cout << "basedata2: " << hasSubdata<basedata2>::value << std::endl; 
} 

但是,如果因爲編譯器檢查所​​有可能性的正確性,你不能使用正常。 你有類似的方式(非常醜陋)採取行動:

template <class T, bool = hasSubdata<T>::value> 
    struct SubdataUser 
    { 
    static void foo() 
    { 
     std::cout << "I can use SubData member :)" << std::endl; 

     typename T::Subdata subinfo(); 
    }   
    }; 

template <class T> 
    struct SubdataUser<T, false> 
    { 
    static void foo() 
    { 
     std::cout << "I can not :(" << std::endl; 
    }   
    }; 

int main() 
{ 
    SubdataUser<basedata1>::foo(); 
    return 0; 
} 

不幸的是,據我所知,你不能因爲如果Member不存在,編譯失敗有一個模板hasMember<Type,Member>::value

但你可能會喜歡這種類型的解決方案

#include <type_traits> 
#include <iostream> 

struct basedata1 
{ 
    struct Subdata1 {}; 
    struct Subdata2 {}; 
    struct Subdata3 {}; 
}; 

struct basedata2 
{ 
    struct Subdata1 {}; 
    //struct Subdata2 {}; 
    struct Subdata3 {}; 
}; 

template <class...> 
    struct Require 
    { 
    enum { value = true }; 
    }; 

template <class T, bool = true> 
    struct Impl 
    { 
    static void foo() 
    { 
     std::cout << "At least one of the members required is not available :(" << std::endl; 
    }   
    }; 

template <class T> 
    struct Impl<T, Require< typename T::Subdata1, 
          typename T::Subdata2, 
          typename T::Subdata3 >::value > 
    { 
    static void foo() 
    { 
     std::cout << "All members are available :)" << std::endl; 

     typename T::Subdata2 my_var; 
    }   
    }; 


int main(int argc, char* argv[]) 
{ 
    Impl<basedata1>::foo(); 
    Impl<basedata2>::foo(); 
    return 0; 
} 

我希望這有助於

+0

謝謝。這看起來好像會起作用。如果baseData和subData都是不同的設置,您是否有設置方法,以便可以設置baseA :: subBaseA和baseDataB :: subBaseB,還是必須分別明確地檢查每一個? – sabbahillel 2015-02-23 22:54:58

+0

我看到這給出了顯式Subdata作爲泛型類T的成員的結果。但是,如何設置它以獲取Subdata作爲模板成員。也就是說,membeA,memberB,memberC需要檢查和處理完成。如果有錯誤結果,我如何在主代碼中設置電話來實際執行檢查? – sabbahillel 2015-02-24 22:30:03

+0

我已經添加了另一個解決方案。你不能寫一個模板'hasMember :: value',因爲只有一個模板參數替換可以失敗而沒有錯誤。如果類型明確寫入並且不存在,則編譯失敗。 – 2015-02-25 17:28:37