我希望可以扔一段代碼,我不明白爲什麼它的行爲是這樣的。相同的指針和可變參數類型的問題
我有兩個問題,下面的代碼。
1)爲什麼兩個實例的this
指針顯示相同的值?這裏程序的輸出:
WJ::WJ(Jit&)
this = 0x7ffff1743950 JV<T, N>::JV(Jit&, indices<Is ...>) [with int ...Is = {0}; T = WJ<float>; int N = 1]
RS<T>::RS(Jit&) [with T = WJ<float>]
this = 0x7ffff1743950 JV<T, N>::JV(Jit&, indices<Is ...>) [with int ...Is = {0}; T = RS<WJ<float> >; int N = 1]
PS<T>::PS(Jit&) [with T = RS<WJ<float> >]
go for it
ptr = 0x7ffff1743950 JV<T, N>::JV(Jit&, JV<T, N>*, indices<Is ...>) [with int ...Is = {0}; T = RS<WJ<float> >; int N = 1]
PS<T>::PS(const PS<T>&) [with T = RS<WJ<float> >; PS<T> = PS<RS<WJ<float> > >]
它顯示了值的2倍0x7ffff1743950
。這讓我感到奇怪,因爲我確信第一個實例在第二個創建之前不會被銷燬。
2)我嘗試製作PS
的深拷貝,其中orig_ptr
被設置爲原來的。這裏使用的設置是遞歸模板實例化設置。所以每個級別的orig_ptr
應該尊重層次並相應地指出。我不明白的是爲什麼代碼用F{{(void(Is),j,ptr->F[Is])...}}
(它在代碼中標記)編譯,爲什麼不用F{{(void(Is),j,&ptr->F[Is])...}}
編譯? (我會假設正確的)。我看不到編譯器正在調用哪個構造函數T
(又名RS<WJ<float> >
)。沒有RS<WJ<float> >::RS(Jit&,RS<WJ<float> >)
只有指針版本存在。
#include<iostream>
#include<array>
struct Jit {};
template <int... Is>
struct indices {};
template <int N, int... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <int... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<class T,int N>
struct JV {
JV(Jit& j) : JV(j,build_indices<N>{}) {}
template<int... Is>
JV(Jit& j, indices<Is...>) :
jit(j), F{{(void(Is),j)...}} {
std::cout << "this = " << (void*)this << " " << __PRETTY_FUNCTION__ << "\n";
}
JV(Jit& j,JV<T,N>* ptr) : JV(j,ptr,build_indices<N>{}) {}
template<int... Is>
JV(Jit& j,JV<T,N>* ptr, indices<Is...>) :
// Why does this not compile with &ptr->F[Is] ??
// What is it calling now (there is no T::T(Jit&,sub_T))
jit(j), orig_ptr(ptr), F{{(void(Is),j,ptr->F[Is])...}} {
std::cout << "ptr = " << (void*)ptr << " " << __PRETTY_FUNCTION__ << "\n";
}
std::array<T,N> F;
JV<T,N>* orig_ptr;
Jit& jit;
};
template<class T>
struct RS : public JV<T,1>
{
RS(Jit &j): JV<T,1>(j) {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
RS(Jit &j, RS* orig): JV<T,1>(j,orig) {
std::cout << "orig = " << orig << " " << __PRETTY_FUNCTION__ << "\n";
}
};
template<class T>
struct PS : public JV<T,1>
{
PS(Jit& j): JV<T,1>(j) {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
PS(const PS& rhs) : JV<T,1>(rhs.jit,const_cast<JV<T,1>*>( static_cast<const JV<T,1>*>(&rhs))) {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
template<class T>
struct WJ
{
WJ(Jit& j) {
std::cout << "WJ::WJ(Jit&)\n";
}
WJ(Jit& j,WJ* ptr) {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
int main() {
Jit j;
PS<RS<WJ<float> > > w(j);
std::cout << "go for it\n";
PS<RS<WJ<float> > > wcopy(w);
}
**編輯**
我加入了指針接口WJ
,這樣的F
實例化過程可以遞歸下降的整個方式。我認爲這可能是由於SFINE。但事實並非如此。
用g ++ - 4.7(Ubuntu/Linaro 4.7.2-4precise1)4.7.2用-O0
試過這個。
**編輯**
@ sehe的回答我指出了正確的方向。當然,第二種類型的JV
構造函數中不需要void(Is)
。僅在第一種類型中,它用於模擬std::fill
。但是我們在初始化列表中!序列操作符的默認實現有助於完全消除(void)Is
。
現在在第二種情況下還有另外一種使用Is
,即ptr->F[Is]
,所以不需要引入人造void
。現在,這看起來更好:
**編輯**
JV(Jit& j,JV<T,N>* ptr, indices<Is...>) :
jit(j), orig_ptr(ptr), F{{T(j,&ptr->F[Is])...}} { }
它編譯現在運行正常!
但是,1問題仍然存在:爲什麼this
2x相同?!?