[使用enable_if选择类构造函数

问题描述 投票:46回答:3

请考虑以下代码:

#include <iostream>
#include <type_traits>

template <typename T>
struct A {
    int val = 0;

    template <class = typename std::enable_if<T::value>::type>
    A(int n) : val(n) {};
    A(...) { }

    /* ... */
};

struct YES { constexpr static bool value = true; };
struct NO { constexpr static bool value = false; };

int main() {
    A<YES> y(10);
    A<NO> n;
    std::cout << "YES: " << y.val << std::endl
              << "NO:  " << n.val << std::endl;
}

我只想使用enable_if为某些类型有选择地定义构造函数A :: A(int)。对于所有其他类型,都有默认的构造函数A :: A(...),当替换失败时,它应该是编译器的默认情况。但这对我来说有意义,编译器(gcc版本4.9.0 20130714)仍在抱怨

sfinae.cpp:在“结构A”的实例中:sfinae.cpp:19:11:从这里需要sfinae.cpp:9:5:错误:在其中没有名为“ type”的类型'struct std :: enable_if'A(int n):val(n){};

对于构造函数来说,这样的事情可能吗?是否可以使用其他构造函数(复制构造函数和move构造函数)?

c++ templates constructor sfinae
3个回答
38
投票

我认为这不能与单个默认模板参数一起使用,因为在实例化类模板时需要解析其值。

我们需要将替换操作推迟到构造函数模板实例化的时候。一种方法是将template参数默认设置为T,并向构造函数添加一个额外的哑参数:

template<typename U = T>
A(int n, typename std::enable_if<U::value>::type* = 0) : val(n) { }

11
投票

通常通过使用匿名默认参数:

完成此操作
A(int n, typename std::enable_if<T::value>::type* = 0) : val(n) {};

您不能使用从类到SFINAE out方法的模板参数。所以一种方法是添加一个伪类型来替换int:

请参阅:http://ideone.com/2Gnyzj

#include <iostream>
#include <type_traits>

template <typename T>
struct A {
    int val = 0;

    template<typename Integer
            ,typename  = typename std::enable_if<T::value && sizeof(Integer)>::type
            >
    A(Integer n) : val(n) {};

    A(...) {}
    /* ... */
};

struct YES { constexpr static bool value = true; };
struct NO { constexpr static bool value = false; };

int main() {
    A<YES> y(10);
    A<NO> n;
    std::cout << "YES: " << y.val << std::endl
              << "NO:  " << n.val << std::endl;
}

这是有效的,因为您使用成员模板参数将SFINAE构造出了构造函数,但是测试始终为true,因此它不会污染您的检查结果


0
投票

使用C ++ 20

您只需在模板中添加requires即可实现:

template <typename U = T> requires U::value
A(int n) : val(n) { }

[requires子句获得一个constant expression,其求值为truefalse,从而确定是否需要在重载解析中使用此方法(如果require子句为true),否则将其忽略。

代码:https://godbolt.org/z/CKTDFE

© www.soinside.com 2019 - 2024. All rights reserved.