![](/img/trans.png)
[英]c++, can I enable several trait class specializations using enable_if instead of copy-paste?
[英]I can't seem to instantiate class specializations with enable_if
我正在嘗試創建一個具有3種可能的模板方法實現版本的類,具體取決於模板類型是三個“類型集”之一。 另外,我試圖將這些對象的實例保留在地圖中。
所以我最初的嘗試是:
class DescriptorType {
public:
int id;
DescriptorType() : id(-1) {}
virtual ~DescriptorType() {}
};
template <typename T>
class Descriptor : public DescriptorType {
public:
T value;
void update(TYPE_CONSTRAINT((TYPE(int) || TYPE(float)))) {
// specific implementation for these types
}
void update(TYPE_CONSTRAINT((TYPE(vec2) || TYPE(vec3) || TYPE(vec4)))) {
// specific implementation for these types
}
void update(TYPE_CONSTRAINT((TYPE(mat2) || TYPE(mat3) || TYPE(mat4)))) {
// specific implementation for these types
}
};
(對於宏,我有一個包含以下內容的包含文件):
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
#define TYPE_CONSTRAINT(x) enable_if_t<x, T>
#define TYPE(x) std::is_same<x, T>::value
但這似乎不起作用。 它可以編譯,但是在我嘗試實例化任何T的Descriptor<T>
那一刻,無論是通用T還是像'int'這樣的具體類型,我都會為所有可能的類型(在本例中為16)遇到鏈接器錯誤。
我的猜測是我使用的enable_if
錯誤。 但是我不確定如何。
更新:
我也嘗試了這種方法,但結果相同:
template <typename T, class Enable = void>
class Descriptor : public DescriptorType {
public:
T value;
void update();
};
template <typename T>
class Descriptor<T, TYPE_CONSTRAINT((TYPE(int) || TYPE(float)))> : public DescriptorType {
public:
T value;
void update() {
//...
}
};
template <typename T>
class Descriptor<T, TYPE_CONSTRAINT((TYPE(vec2) || TYPE(vec3) || TYPE(vec4)))> : public DescriptorType {
public:
T value;
void update() {
//...
}
};
template <typename T>
class Descriptor<T, TYPE_CONSTRAINT((TYPE(mat2) || TYPE(mat3) || TYPE(mat4)))> : public DescriptorType {
public:
T value;
void update() {
//...
}
};
但是會得到相同的鏈接器錯誤。
聲明不帶參數的函數的語法foo(void)
嚴格用於C兼容性。 當模板替換產生void
時,它將不起作用。 (您實際上並沒有變得void
,但根據評論,這是您的意圖。)
SFINAE僅在立即聲明中使用模板參數。 您不能使用類模板的參數禁用成員函數。 (這條規則很煩人,但即使是龐大的概念提案也沒有建議對其進行更改。)
要基於類模板參數禁用成員,您需要添加偽造的模板參數,然后使SFINAE看起來依賴於該模板參數。 SFINAE也可以安全地放在模板參數默認參數中:
#define TYPE_CONSTRAINT(x) enable_if_t< (bogus(), x) >
template< typename bogus = void,
typename = TYPE_CONSTRAINT((TYPE(int) || TYPE(float))) >
void update() {
仍然存在過載的問題。 SFINAE在重載解決時發生,但是在聲明重載時檢查其相互兼容性。 僅SFINAE不足以授予不同功能的兼容性,因此您也需要破壞該安全機制。
#define TYPE_CONSTRAINT(x) enable_if_t< x, bogus >
template< typename bogus = void,
void * = (TYPE_CONSTRAINT((TYPE(int) || TYPE(float))) *) nullptr >
void update() …
template< typename bogus = int, // Use different types here
int * = (TYPE_CONSTRAINT((TYPE(vec2) || TYPE(vec3))) *) nullptr >
void update() …
template< typename bogus = char,
char * = (TYPE_CONSTRAINT((TYPE(mat2) || TYPE(mat3))) *) nullptr >
void update() …
http://coliru.stacked-crooked.com/a/64e957e0bb29cde9
認真地說,這是解決方法。 在光明的一面,您參觀了SFINAE的最黑暗的角落,並活着講述這個故事!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.