2016-04-14 20 views
2

如何在專用和非專用版本的C++類之間共享代碼?在專用和非專用模板結構之間共享代碼

這裏是什麼,我試圖完成一個人爲的例子:

#include <iostream> 
using namespace std; 

template <size_t n> struct Y { 
    int one() { return 1; } 
    int two(); 
}; 

template <> struct Y<1> { 
    int one() { return 11; } 
    int two(); 
}; 

template <size_t n> int Y<n>::two() { return one() * 2; } 

int main() { 
    Y<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 

這種失敗在鏈接時使用:

Undefined symbols for architecture x86_64: 
    "Y<1ul>::two()", referenced from: 
     _main in test-7c4ebe.o 

但是,如果我改變Y<1> X;Y<2> X;,編譯成功正好。

我在這裏的目標是使用two()的示例實現來獲取該類的專用版和非專用版。

我能解決這個問題,繼承,像這樣:

#include <iostream> 
using namespace std; 

struct mixin { 
    virtual int one() = 0; 
    int two() { return one() * 2; } 
}; 

template <size_t n> struct Y : public mixin { 
    int one() { return 1; } 
}; 

template <> struct Y<1> : public mixin { 
    int one() { return 11; } 
}; 

int main() { 
    Y<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 

但我認爲,招致每次調用不必要的V-表查找到Y<n>.two(),對不對?

有什麼辦法可以在專用和非專用版本之間共享代碼,而不會濫用繼承並引發v表查找調用?

+0

define *濫用* in傳承。 – SergeyA

+0

@SergeyA在我看來,這種問題應該是可以解決的,根本不需要繼承,儘管如果有一些解決方案使用繼承,但是避免了v-table查找,那就沒問題。 –

+0

@SergeyA:好的,我誤解了。 – AnT

回答

2

根本不需要將one方法添加到mixin。只需要使用非虛擬two方法mixin與派生類Y共享其實現並使用CRTP。

#include <iostream> 
using namespace std; 

template <class Derive> 
struct mixin { 
    int two() { return ((Derive *)this)->one() * 2; } 
}; 

template <size_t n> struct Y : public mixin <Y<n>> { 
    int one() { return 1; } 
}; 

template <> struct Y<1> : public mixin <Y<1>> { 
    int one() { return 11; } 
}; 

int main() { 
    Y<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 
2

可以speciliaze的一個方法,而不是類專業化:

template <size_t n> struct Y { 
    int one() { return 1; } 
    int two() { return one() * 2; } 
    int theird(); // declare only for Y<N> 
}; 

template <> 
int Y<1>::one() { return 11; } 

// only for Y<1> 
template <> 
int Y<1>::theird() { return one()*two();} 
+0

啊,是的。這可以在這種情況下工作,但我想要在'Y <1>'上定義方法,而'Y '完全不存在。 –

+1

如果您僅聲明此類方法並僅將它們專門用於Y <1>,則可以這樣做。 – AnatolyS

+0

只是爲了澄清您的意見,您的意思是我可以定義我只想爲Y <1>定義Y 的方法,但是隻針對Y <1>執行它? –

1

相反CRTP的,你也可以做到這一點反過來:

#include <iostream> 
using namespace std; 

template <size_t n> struct Y { 
    int one() { return 1; } 
}; 

template <> struct Y<1> { 
    int one() { return 11; } 
}; 

template <size_t n> 
struct mixin : Y<n> { 
    int two() { return Y<n>::one() * 2; } 
}; 

int main() { 
    mixin<1> X; 
    cout << X.one(); 
    cout << X.two(); 
    return 0; 
} 

或可替代:

template <class P> 
struct mixin : P { 
    int two() { return P::one() * 2; } 
}; 

mixin<Y<1>> X;