2017-03-17 57 views
0

我認爲這是不可能的什麼,我問,但我想是完全確定的,所以我問反正..在結構型注射

我想從一個模板結構得到一個編譯時間值(可以在constexpr函數中使用),但是沒有在模板中傳遞,但以其他方式注入。

這是很難解釋,我會用一些代碼嘗試:

template<int A> 
struct MagicStruct 
{ 
enum { current = A, injected = /* magic */} 
}; 

template<int A, int B> 
struct InjectionStruct 
{ 
enum { first=A, second=B} 
/*... injection of B in MagicStruct<A> ... */ 
}; 

static const int AVALUE = 1; 
static const int BVALUE = 2; 

static const int CVALUE = InjectionStruct<AVALUE, BVALUE>::first; //== 1 
static const int CVALUE = InjectionStruct<AVALUE, BVALUE>::second; //== 2 
static const int DVALUE = MagicStruct<AVALUE>::injection; //== 2 

有一些訣竅,我不知道這將允許?

[編輯]我想在輸入獲得DVALUE只是作爲安勤模板參數

+0

關於你的[編輯]:如果你有20'InjectionStruct',哪一個是定義你的''MagicStruct'值injected'?正如我在答案中所解釋的那樣,您需要在'MagicStruct'和'InjectionStruct'提供數據之間建立關係。 –

+0

好點e複雜的問題:)它沒有太多的道理我知道..但我認爲它應該採取一個評估/宣佈/定義/無論作爲最後.. – user3770392

回答

2

你可以做injectedstatic int代替:

template<int A> 
struct MagicStruct 
{ 
    enum { current = A }; 
    static int injected; 
}; 

template<int A> 
int MagicStruct<A>::injected; 

然後給InjectionStruct靜態成員,其實例將在MagicStruct<A>::injected填寫:

template<int A, int B> 
struct InjectionStruct : MagicStruct<A> 
{ 
    enum { first=A, second=B}; 

    struct filler { 
     filler() { MagicStruct<A>::injected = B; } 
    }; 

    static filler inject; 
}; 

template <int A, int B> 
typename InjectionStruct<A,B>::filler InjectionStruct<A,B>::inject; 

然後進行注射,你只需要在某處使用inject,或者明確地實例化它:

static const int AVALUE = 1; 
static const int BVALUE = 2; 

static const int CVALUE = InjectionStruct<AVALUE, BVALUE>::first; //== 1 
static const int DVALUE = InjectionStruct<AVALUE, BVALUE>::second; //== 2 
//explicit instantiation 
template InjectionStruct<AVALUE,BVALUE>::filler 
     InjectionStruct<AVALUE,BVALUE>::inject; 
static const int EVALUE = MagicStruct<AVALUE>::injected; //== 2 

或者,你可以隱藏在injected您使用檢索firstsecond一些功能的實例。


這是一個瘋狂的實現,它依賴於通過模板實例化注入函數的實現。這可能不是你的編譯器的工作,如果它不執行有關標準正確的規則,但它是有趣儘管如此,在編譯時完全透明的工作原理:

template<typename>struct Type{}; 

template<int A> 
struct MagicStruct 
{ 
    friend constexpr int get_injected(Type<MagicStruct<A>>); 
    static constexpr int current() { return A; } 

    template <int V = get_injected(Type<MagicStruct<A>>{})> 
    static constexpr int injected() { return V; } 
}; 


template<int A, int B> 
struct InjectionStruct 
{ 
    static constexpr int first() { return A; } 
    static constexpr int second() { return B; } 

    friend constexpr int get_injected(Type<MagicStruct<A>>) { return B; } 
}; 

你這個實現使用幾乎完全一樣,你想:

static const int AVALUE = 1; 
static const int BVALUE = 2; 

static const int CVALUE = InjectionStruct<AVALUE, BVALUE>::first(); //== 1 
static const int DVALUE = InjectionStruct<AVALUE, BVALUE>::second(); //== 2 
static const int EVALUE = MagicStruct<AVALUE>::injected(); //== 2 

Live demo

+0

隊友這種技術是真棒,我試過你之前發佈的鏈接,它似乎工作。你現在已經刪除了f函數,所以我會再試一次。非常感謝! – user3770392

+1

真的很好的解決方案,但不知道這是編譯時間。 –

+0

是的,我想做一些更多的測試..靜態部分似乎很可怕;) – user3770392

1

將在下面幫你?

template<int A, int B> 
struct InjectionStruct 
{ 
    constexpr static int first = A; 
    constexpr static int second = B; 
    constexpr static int MAGIC = B; 
}; 

template<int A, class Injection> 
struct MagicStruct 
{ 
    constexpr static int current = A; 
    constexpr static auto injected = Injection::MAGIC; 
}; 
static const int AVALUE = 1; 
static const int BVALUE = 2; 

static const int CVALUE = InjectionStruct<AVALUE, BVALUE>::first; //== 1 
static const int CVALUE = InjectionStruct<AVALUE, BVALUE>::second; //== 2 
static const int DVALUE = MagicStruct<AVALUE, InjectionStruct<AVALUE, BVALUE>>::injected; //== 2 

很難給出更深入的建議,不知道你想要注入什麼。

+0

謝謝你:)請檢查我編輯的帖子。在我的情況下,我想通過僅使用AVALUE來獲得DVALUE。當我使用MagicStruct時,我不知道BVALUE – user3770392

1

您需要InjectionStructMagicStruct之間的一些關係。出於這個原因,我在injected值中包含了一個額外的模板參數,在InjectionStruct中包含了typdef

第一個例子使用InjectionStruct本身定義的特定MagicStruct:

實施例:

// MagicStruct is generic 
template<int A, int INJ> 
struct MagicStruct 
{ 
    enum { current = A, injected = INJ}; 

}; 

// Injection struct has it own copy of MagicStruct 
template<int A, int B> 
struct InjectionStruct 
{ 
    enum { first=A, second=B}; 

    // Provide custom magic number 
    constexpr static int provideInjection(){ return B;} 

    // Own copy of magicStruct, injected by this template instance. 
    template <int X> struct MagicStruct: public ::MagicStruct<X,provideInjection()>{}; 
}; 

constexpr static const int AVALUE = 1; 
constexpr static const int BVALUE = 2; 

constexpr static const int CVALUE1 = InjectionStruct<AVALUE, BVALUE>::first; //== 1 
constexpr static const int CVALUE2 = InjectionStruct<AVALUE, BVALUE>::second; //== 2 
// Using a specific InjectionStruct, provies the MagicStruct with one argument. 
constexpr static const int DVALUE3 = InjectionStruct<AVALUE, BVALUE>::MagicStruct<AVALUE>::injected; //== 2 


int main() 
{ 
    std::cout << CVALUE1 << std::endl; 
    std::cout << CVALUE2 << std::endl; 
    std::cout << DVALUE3 << std::endl; 

    return 0; 
} 

在下面的溶液中,MagicStruct把它魔法值從默認InjectionStruct這是修復。

// InjectionStruct is generic. 
template<int A, int B> 
struct InjectionStruct 
{ 
    enum { first=A, second=B}; 
    constexpr static int provideInjection(){ return A+B;} 
}; 


constexpr static const int AVALUE = 1; 
constexpr static const int BVALUE = 2; 

// Define MagicStruct based on a specific InjectionStruct 
template<int A, int INJ = InjectionStruct<A,BVALUE>::provideInjection()> 
struct MagicStruct 
{ 
    enum { current = A, injected = INJ}; 
}; 

constexpr static const int CVALUE1 = InjectionStruct<AVALUE, BVALUE>::first; //== 1 
constexpr static const int CVALUE2 = InjectionStruct<AVALUE, BVALUE>::second; //== 2 
constexpr static const int DVALUE1 = MagicStruct<3>::injected; // == 5 
constexpr static const int DVALUE2 = MagicStruct<DVALUE1>::injected; // == 7 
constexpr static const int DVALUE3 = MagicStruct<DVALUE2>::injected; // == 9 


int main(int n, char* args[]) 
{ 
    std::cout << CVALUE1 << std::endl; 
    std::cout << CVALUE2 << std::endl; 
    std::cout << DVALUE1 << std::endl; 
    std::cout << DVALUE2 << std::endl; 
    std::cout << DVALUE3 << std::endl; 

    return 0; 
} 
+0

謝謝你的嘗試:)檢查我編輯過的帖子。在我的情況下,我想通過僅使用AVALUE來獲得DVALUE。 – user3770392

+0

DVALUE本質上是BVALUE的別名,因此它始終依賴於BVALUE。我想你想要的是,編譯器查看InjectionStruct的所有定義,並根據AVALUE選擇合適的定義。這種行爲是不可能的,即使是這樣,你也不想這樣做,因爲它不是一對一映射。 我很遺憾地說,但你應該考慮一個不同的設計。 – OutOfBound

+0

我只是在這裏做實驗,所以沒有設計問題。我只是想要一種方法來獲得編譯時間值的模板 MagicStruct,它已被插入不與該模板值。 – user3770392