2015-11-17 66 views
1

我知道這個代碼看起來很奇怪,但我想知道是否有任何方法可以使它編譯。使用is作爲模板類型參數時,可以訪問類字段嗎?

template<typename T> 
class A 
{ 
public: 
    enum 
    { 
     template_class_id = T::class_id 
    }; 
}; 

class B : public A<B> 
{ 
public: 
    enum 
    { 
     class_id = 0x1234 
    }; 
}; 

而且我得到這樣的錯誤:

clang++ test.cpp            
test.cpp:7:32: error: no member named 'class_id' in 'B' 
     template_class_id = T::class_id 
          ~~~^ 
test.cpp:11:18: note: in instantiation of template class 'A<B>' requested here 
class B : public A<B> 
       ^
1 error generated. 

回答

5

B在實例化基類A<B>時是不完整的類型,因此B::class_id在該點不存在。

爲了得到你需要的東西,你需要延遲template_class_id成員的實例化。


一種可能性將是使template_class_id一個C++ 14的成員變量的模板:

template<typename T> 
class A 
{ 
public: 
    template <typename U=T> 
    static constexpr int template_class_id = U::class_id; 
}; 

class B : public A<B> 
{ 
public: 
    static constexpr int class_id = 0x1234; 
}; 

Live Demo

不幸的是,這意味着你需要參考template_class_idtemplate_class_id<>,但它不不需要任何額外的類型。


另一種選擇是依靠traits類:

template <typename T> struct ClassId; 

template<typename T> 
class A { 
public: 
    static constexpr int template_class_id = ClassId<T>::value; 
}; 

class B; 
template <> struct ClassId<B> { 
    static constexpr int value = 0x1234; 
}; 

class B : public A<B> { 
}; 

Live Demo

我覺得這是非常靈活,並不需要你切換到功能。這確實意味着id在詞法上與你的類定​​義不同,但我認爲這不是一個大問題。

+0

你的第二種方法似乎可用。 – jayatubi

+0

經過大量測試後,我發現template_class_id只有在對類A的聲明「不在」類的聲明時纔可用。我不能在類A的聲明中使用它,例如在類A中定義一個枚舉與template_class_id的值。 – jayatubi

+0

@jayatubi當然,這是因爲odr-using'template_class_id'會導致它被實例化。你想用它做什麼? – TartanLlama

3

問題是class B : public A<B>。當您實例化A<B>時,B是不完整的類型,因此您不能使用B::class_id

下面將工作:

template<typename T> 
class A 
{ 
public: 
    static constexpr int get_template_class_id() { return T::get_class_id(); } 
}; 

class B : public A<B> 
{ 
public: 
    static constexpr int get_class_id() { return 0x1234; } 
}; 

這是因爲成員函數不實例化直到它們被使用,而在這一點上B將不再是不完整的。

+0

我試過'constexpr',但它不能保證它是一個真正的常量數據,我不能用它來初始化枚舉或在開關盒中使用它。 – jayatubi

+0

@jayatubi http://ideone.com/sUo1Ck – Simple

相關問題