簡體   English   中英

我似乎無法使用enable_if實例化類專業

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM