如何使用enable_if根据类的模板参数启用成员函数

发布于 2024-10-01 15:57:16 字数 1107 浏览 3 评论 0 原文

在代码中:

template<class T>
struct is_builtin
{
    enum {value = 0};
};

template<>
struct is_builtin<char>
{
    enum {value = 1};
};

template<>
struct is_builtin<int>
{
    enum {value = 1};
};

template<>
struct is_builtin<double>
{
    enum {value = 1};
};

template<class T>
struct My
{
    typename enable_if<is_builtin<T>::value,void>::type f(T arg)
    {
        std::cout << "Built-in as a param.\n";
    }


    typename enable_if<!is_builtin<T>::value,void>::type f(T arg)
    {
        std::cout << "Non - built-in as a param.\n";
    }
};

struct A
{
};

int main()
{
    A a;
    My<int> m;
    My<A> ma;
    m.f(1);
    ma.f(a);
    return 0;
}

我收到错误:

error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>'    

显然我不明白如何使用enable_if。我的想法是,我可以在编译期间启用一组成员函数中的一个或第二个成员函数,但它不起作用。谁能向我解释一下如何正确执行此操作?
已编辑
我真正无法理解的是为什么其中一个 def 中没有 typedef 。编译器找不到它并且不会编译它。

In code:

template<class T>
struct is_builtin
{
    enum {value = 0};
};

template<>
struct is_builtin<char>
{
    enum {value = 1};
};

template<>
struct is_builtin<int>
{
    enum {value = 1};
};

template<>
struct is_builtin<double>
{
    enum {value = 1};
};

template<class T>
struct My
{
    typename enable_if<is_builtin<T>::value,void>::type f(T arg)
    {
        std::cout << "Built-in as a param.\n";
    }


    typename enable_if<!is_builtin<T>::value,void>::type f(T arg)
    {
        std::cout << "Non - built-in as a param.\n";
    }
};

struct A
{
};

int main()
{
    A a;
    My<int> m;
    My<A> ma;
    m.f(1);
    ma.f(a);
    return 0;
}

I'm getting an error:

error C2039: 'type' : is not a member of 'std::tr1::enable_if<_Test,_Type>'    

Obviously I don't understand how to use enable_if. What I was thinking was that I can enable one or the second one member function from a set of member functions during compilation time but it does not work. Could anyone please explain to me how to do it correctly?
Edited
What I really can't understand is why isn't there typedef in one of those def. Compiler cannot find it and it wont compile it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

辞取 2024-10-08 15:57:17

您不能使用类模板参数来获取成员函数的 SFINAE。

您需要

  • 使成员函数成为成员函数模板,并在成员函数模板的模板参数上使用 enable_if,或者

  • 将成员函数 f 移动到策略类中,并使用 enable_if 专门化类模板。< /p>

You can't use class template parameters to get SFINAE for member functions.

You either need to

  • make the member function a member function template instead and use enable_if on the member function template's template parameters or

  • move the member function f into a policy class and specialize the class template using enable_if.

ゝ偶尔ゞ 2024-10-08 15:57:17

它的工作原理如下(请注意,为了方便起见,我用 std::is_arithmetic 替换了您的 is_builtin 特征,并使用了更多 C++11 内容,但它无论如何都可以工作):

template<class T>
struct My
{
    template<typename T_ = T, std::enable_if_t<std::is_arithmetic<T_>::value>* = nullptr>
    void f(T_ arg)
    {
        std::cout << "Built-in as a param.\n";
    }

    template<typename T_ = T, std::enable_if_t<!std::is_arithmetic<T_>::value>* = nullptr>
    void f(T_ arg)
    {
        std::cout << "Non - built-in as a param.\n";
    }
};

< a href="http://coliru.stacked-crooked.com/a/3dfb1fb7c5e78e02" rel="nofollow noreferrer">DEMO

关键部分是将模板参数带入直接上下文 通过使用默认函数模板参数 T_ ,它等于类模板参数 T。有关更多详细信息,请参阅此问题

Here's how it works (note that for convenience I replaced your is_builtin trait with std::is_arithmetic and used further C++11 stuff, but it works any way):

template<class T>
struct My
{
    template<typename T_ = T, std::enable_if_t<std::is_arithmetic<T_>::value>* = nullptr>
    void f(T_ arg)
    {
        std::cout << "Built-in as a param.\n";
    }

    template<typename T_ = T, std::enable_if_t<!std::is_arithmetic<T_>::value>* = nullptr>
    void f(T_ arg)
    {
        std::cout << "Non - built-in as a param.\n";
    }
};

DEMO

The crucial part is to bring the template parameter into the immediate context by using a default function template parameter T_ which equals the class template parameter T. For more details, see this question.

陪你到最终 2024-10-08 15:57:17

您可以使用修改后的enable_if来修复代码

template < typename T >
struct __Conflict {};

template <bool B, class T = void>
struct __enable_if { typedef __Conflict<T> type; };

template <class T>
struct __enable_if<true, T> { typedef T type; };

使用示例:

template <typename T>
class Lazy
{
public:
    void _ctor(bool b);
    void _ctor(typename __enable_if<!std::is_same<T, bool>::value, T>::type);
};

template <typename T>
void Lazy<T>::_ctor(bool b)
{
    std::cout << "bool " << b << std::endl;
};

template <typename T>
void Lazy<T>::_ctor(typename __enable_if<!std::is_same<T, bool>::value, T>::type t)
{
    std::cout << "T " << t << std::endl;
};

int main(int argc, char **argv)
{
    Lazy<int> i;
    i._ctor(10);
    i._ctor(true);

    Lazy<bool> b;
    b._ctor(true);

    return 0;
}

You can fix your code by using modified enable_if

template < typename T >
struct __Conflict {};

template <bool B, class T = void>
struct __enable_if { typedef __Conflict<T> type; };

template <class T>
struct __enable_if<true, T> { typedef T type; };

Example of usage:

template <typename T>
class Lazy
{
public:
    void _ctor(bool b);
    void _ctor(typename __enable_if<!std::is_same<T, bool>::value, T>::type);
};

template <typename T>
void Lazy<T>::_ctor(bool b)
{
    std::cout << "bool " << b << std::endl;
};

template <typename T>
void Lazy<T>::_ctor(typename __enable_if<!std::is_same<T, bool>::value, T>::type t)
{
    std::cout << "T " << t << std::endl;
};

int main(int argc, char **argv)
{
    Lazy<int> i;
    i._ctor(10);
    i._ctor(true);

    Lazy<bool> b;
    b._ctor(true);

    return 0;
}
挽手叙旧 2024-10-08 15:57:17

enable_if 需要一个元函数。要使用布尔值,您需要enable_if_c。我很惊讶你在解释这个问题时没有遇到错误。

您可以通过在内部声明一个“类型”typedef 来修复您的元函数,该类型定义本身就是它本身。然后您可以使用 boost::enable_if>::type

enable_if expects a metafunction. To use a bool you need enable_if_c. I'm surprised you're not getting errors explaining THAT problem.

You can fix your metafunction by declaring a 'type' typedef inside that is simply itself. Then you can use boost::enable_if<is_builtin<T>>::type

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文