【问题标题】:SFINAE enable_if explicit constructorSFINAE enable_if 显式构造函数
【发布时间】:2014-11-15 18:35:58
【问题描述】:

我正在尝试通过enable_if 在显式和隐式转换构造函数之间切换。

我的代码目前看起来像

#include <type_traits>
#include <cstdint>

enum class enabled {};

template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type;
template <bool B, typename T = void> using disable_if_t = typename std::enable_if<!B, T>::type;

template <std::intmax_t A> struct SStruct
{
    static constexpr std::intmax_t a = A;
};

template <typename T> struct SCheckEnable : std::integral_constant<bool, T::a == 0>
{
};

template <typename U, typename T> class CClass
{
    public:
        template <typename T2, enable_if_t<SCheckEnable<U>::value, enabled>...> constexpr CClass(T2 v) : val(v) {};
        template <typename T2, disable_if_t<SCheckEnable<U>::value, enabled>...> explicit constexpr CClass(T2 v) : val(v) {};

    private:
        T val;
};

int main()
{
    CClass<SStruct<0>, double> a = 1;                             // should use implicit constructor
    CClass<SStruct<1>, double> b = CClass<SStruct<1>, double>(1); // should use explicit constructor
}

enable_ifs 中的true 依赖于模板参数U

如果我尝试在启用 g++ 4.9.1--std=c++11 的情况下编译这个最小示例,我会收到以下错误

sfinae.cpp: In substitution of ‘template<bool B, class T> using disable_if_t = typename std::enable_if<(! B), T>::type [with bool B = true; T = enabled]’:
sfinae.cpp:13:52:   required from here
sfinae.cpp:7:95: error: no type named ‘type’ in ‘struct std::enable_if<false, enabled>’
 template <bool B, typename T = void> using disable_if_t = typename std::enable_if<!B, T>::type;
                                                                                               ^
sfinae.cpp:19:68: error: prototype for ‘constexpr CClass<U, T>::CClass(T2)’ does not match any in class ‘CClass<U, T>’
 template <typename U, typename T> template <typename T2> constexpr CClass<U, T>::CClass(T2 v) : val(v)
                                                                    ^
sfinae.cpp:13:77: error: candidates are: template<class U, class T> template<class T2, int ...<anonymous> > constexpr CClass<U, T>::CClass(T2)
   template <typename T2, disable_if_t<true, enabled>...> explicit constexpr CClass(T2 v);
                                                                             ^
sfinae.cpp:12:67: error:                 template<class U, class T> template<class T2, enabled ...<anonymous> > constexpr CClass<U, T>::CClass(T2)
   template <typename T2, enable_if_t<true, enabled>...> constexpr CClass(T2 v);
                                                                   ^

知道如何在此处根据参数U 在显式和隐式构造之间进行选择吗?

【问题讨论】:

  • 我可以得到this to work just fine。不知道你的代码和我的代码有什么区别。
  • constexpr 可能是造成这种情况的原因吗?
  • 没有。它不应该对 SFINAE 有任何影响。可能与在课堂之外定义它以及你这样做的方式有关,但我并不完全相信。
  • 如果 true 这里不是实际代码,而是依赖于模板参数,那么您的代码应该可以工作。
  • 为了让 SFINAE 发生,构造需要包含来自 immediate 模板的模板参数。

标签: c++ templates c++11 sfinae enable-if


【解决方案1】:

使用

template <class...> struct null_v : std::integral_constant<int, 0> {};

并将构造函数定义为

template <typename T2,
          long = null_v<enable_if_t<SCheckEnable<U>::value, T2>>::value>
constexpr CClass(T2 v) : val(v) {};

template <typename T2,
          int = null_v<disable_if_t<SCheckEnable<U>::value, T2>>::value>
explicit constexpr CClass(T2 v) : val(v) {};

使参数依赖并实际实例化。 Demo.

[temp.deduct]/8:

如果替换导致无效的类型或表达式,请输入 扣除失败。无效的类型或表达式是 如果使用替换的参数编写,则格式错误。

在您的情况下,错误发生在任何替换之外,因此这不会导致演绎失败,而是使您的代码格式错误。

【讨论】:

  • 按应有的方式编译和工作...我的尝试和您的解决方案之间的区别到底在哪里?
  • 如果我正确理解了@0x499602D2 注释,enable_if 需要使用T2“处理”某些内容,因为这是启用或禁用特定功能的模板参数。我做对了吗? :)
  • @Uroc327 编辑了答案。
猜你喜欢
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多