简体   繁体   English

在 class 模板 T 上需要有关 SFINAE 的帮助

[英]Need help on SFINAE on class template T

I'm writing a template class Foo<T> which I only want to allow certain types of T .我正在编写一个模板 class Foo<T> ,我只想允许某些类型的T I have been playing around for quite a while and now the class compiles, but in the presence of a second template non-type parameter, I couldn't figure out how to instantiate it correctly.我已经玩了很长时间,现在 class 编译了,但是在存在第二个模板非类型参数的情况下,我无法弄清楚如何正确实例化它。 How can I give it a default value so that I can simply call Foo<int> and so on?我怎样才能给它一个默认值,这样我就可以简单地调用Foo<int>等等?

#include <iostream>
#include <utility>
#include <type_traits>

template<typename T>
struct is_foo_type {
    using type = typename std::enable_if_t<
        // std::is_same_v<T, vec2>   ||
        // std::is_same_v<T, vec3>   ||
        // std::is_same_v<T, vec4>   ||
        // std::is_same_v<T, ivec2>  ||
        // std::is_same_v<T, ivec3>  ||
        // std::is_same_v<T, ivec4>  ||
        // std::is_same_v<T, mat2>   ||
        // std::is_same_v<T, mat3>   ||
        // std::is_same_v<T, mat4>   ||
        // std::is_same_v<T, mat2x2> ||
        // std::is_same_v<T, mat2x3> ||
        // std::is_same_v<T, mat2x4> ||
        // std::is_same_v<T, mat3x2> ||
        // std::is_same_v<T, mat3x3> ||
        // std::is_same_v<T, mat3x4> ||
        // std::is_same_v<T, mat4x2> ||
        // std::is_same_v<T, mat4x3> ||
        // std::is_same_v<T, mat4x4> ||
        std::is_same_v<T, int>    ||
        std::is_same_v<T, bool>   ||
        std::is_same_v<T, float>  ||
        std::is_same_v<T, char>
    >;
};

template<typename T, typename is_foo_type<T>::type = 0>
class Foo {
public:
    T _x;
    Foo() = default;
    Foo(const T& x) : _x(x) {};
    void Increment(const T& x) { _x += x; }
};

int main() {
    Foo<int> a{123};  // compiler error

    // using foo_int   = Foo<int>;    // compiler error
    // using foo_bool  = Foo<bool>;   // compiler error
    // using foo_float = Foo<float>;  // compiler error

    // using foo_var = std::variant<foo_int, foo_bool, foo_float>;

    // foo_var my_variant;
}

std::enable_if_t<true> gives you a void type. std::enable_if_t<true>给你一个void类型。 Then you're trying to do something like然后你试图做类似的事情

template<typename T, void = 0>

which doesn't work for an obvious reason.由于明显的原因,这不起作用。 You can kind of fix the problem with std::enable_if_t<..., int> .您可以使用std::enable_if_t<..., int>解决问题。

But note that you're not doing SFINAE here.但请注意,您不是在此处执行 SFINAE。 Substitution will be a hard error in your example - SFINAE works only in the immediate context.在您的示例中,替换将是一个严重错误 - SFINAE 仅在直接上下文中起作用。

Consider the following alternative implementation:考虑以下替代实现:

template<typename T>
struct is_foo_type : std::disjunction<
        std::is_same<T, int>,
        std::is_same<T, bool>,
        std::is_same<T, float>,
        std::is_same<T, char>
> {};

template<typename T, typename = std::enable_if_t<is_foo_type<T>::value>>
class Foo { ... };

and note in which context std::enable_if is used.并注意在哪个上下文中使用了std::enable_if

In this particular case you could also use a non-type template parameter在这种特殊情况下,您还可以使用非类型模板参数

template<typename T, std::enable_if_t<is_foo_type<T>::value, int> = 0>
class Foo { ... };

to avoid the possibility of "overriding" substitution when the second type is provided explicitly, eg Foo<T, void> .以避免在显式提供第二种类型时“覆盖”替换的可能性,例如Foo<T, void>

Try adding multiple template尝试添加多个模板
Syntax: template<typename T, typename V> .语法: template<typename T, typename V>
And use it accordingly并相应地使用它

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM