简体   繁体   English

我似乎无法使用enable_if实例化类专业

[英]I can't seem to instantiate class specializations with enable_if

I'm trying to make a class that has 3 possible versions of a template method implementation, depending on the template type being of one of three 'type sets'. 我正在尝试创建一个具有3种可能的模板方法实现版本的类,具体取决于模板类型是三个“类型集”之一。 Also, I'm trying to keep instances of these objects in a map. 另外,我试图将这些对象的实例保留在地图中。

So my initial attempt was: 所以我最初的尝试是:

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
    }
};

(I have an include file with the following -- for the macros): (对于宏,我有一个包含以下内容的包含文件):

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

But it doesn't seem to work. 但这似乎不起作用。 It compiles but the minute I try to instantiate a Descriptor<T> for any T, be it the generic T or a concrete type like 'int' I get linker errors for all possible types (16 in my case). 它可以编译,但是在我尝试实例化任何T的Descriptor<T>那一刻,无论是通用T还是像'int'这样的具体类型,我都会为所有可能的类型(在本例中为16)遇到链接器错误。

My guess is I'm using enable_if wrong. 我的猜测是我使用的enable_if错误。 But I'm not sure how. 但是我不确定如何。

UPDATE: 更新:

I also tried this approach with same results: 我也尝试了这种方法,但结果相同:

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() {
        //...
    }
};

But get the same linker errors. 但是会得到相同的链接器错误。

The syntax foo(void) to declare a function with no parameters is strictly for C compatibility. 声明不带参数的函数的语法foo(void)严格用于C兼容性。 It doesn't work when void comes from template substitution. 当模板替换产生void时,它将不起作用。 (You're not actually getting void , but per the comments it was your intent.) (您实际上并没有变得void ,但根据评论,这是您的意图。)

SFINAE only works with template parameters in the immediate declaration. SFINAE仅在立即声明中使用模板参数。 You cannot disable member functions using parameters of the class template. 您不能使用类模板的参数禁用成员函数。 (This rule is very annoying, but not even the massive concepts proposal has suggested to change it.) (这条规则很烦人,但即使是庞大的概念提案也没有建议对其进行更改。)

To disable members based on the class template parameters, you need to add a bogus template parameter, and then make the SFINAE appear to depend on it. 要基于类模板参数禁用成员,您需要添加伪造的模板参数,然后使SFINAE看起来依赖于该模板参数。 SFINAE can also be safely placed in template parameter default arguments: SFINAE也可以安全地放在模板参数默认参数中:

#define TYPE_CONSTRAINT(x) enable_if_t< (bogus(), x) >


template< typename bogus = void,
    typename = TYPE_CONSTRAINT((TYPE(int) || TYPE(float))) >
void update() {

There's still the remaining issue of overloading. 仍然存在过载的问题。 SFINAE happens at overload resolution time, but overloads are checked for mutual compatibility as they are declared. SFINAE在重载解决时发生,但是在声明重载时检查其相互兼容性。 SFINAE alone is not enough to grant compatibility to different functions, so you'll need to defeat that safety mechanism too. 仅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 http://coliru.stacked-crooked.com/a/64e957e0bb29cde9

Seriously, this is the workaround. 认真地说,这是解决方法。 On the bright side, you have visited the darkest corner of SFINAE and lived to tell the tale! 在光明的一面,您参观了SFINAE的最黑暗的角落,并活着讲述这个故事!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++,我可以使用enable_if代替复制粘贴来启用多个特征类专业化吗? - c++, can I enable several trait class specializations using enable_if instead of copy-paste? enable_if 如何帮助 select 专业化 class 模板? - How does enable_if help select specializations of a class template? std :: enable_if的模糊部分特化 - ambiguous partial specializations with std::enable_if 具有std :: enable_if的多个变量模板专业化 - Multiple variable template specializations with std::enable_if (本来是两个问题,但现在已经回答了一个问题)如何使用enable_if来声明模板类的特殊性? - (Was originally two questions, but one is now answered) How to use enable_if to declare template class specializations? 我可以用 decltype 替换 enable_if - Can I Just Replace enable_if With decltype 我可以将enable_if与typedef一起使用吗? - Can I use enable_if together with typedef? 如何使用 std::enable_if 元函数实现类模板函数? - How can I implement a class template function with a std::enable_if metafunction? 如何 enable_if 具有可变参数模板参数的类? - How do I enable_if a class with variadic template arguments? 带有enable_if方法的枚举类 - Enum class with enable_if methods
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM