繁体   English   中英

跨编译器的std :: enable_if的不同行为(取决于外部类模板参数)

[英]Different behavior across compilers for std::enable_if (dependent on Outer class template parameters)

我有一个嵌套( Inner )类,为此,我想enable_if构造,这取决于模板多少个参数( Args )封装类( Outer )了。

我想出了下面的代码,只是发现它在某些编译器上可以正常编译,而在某些编译器上则可以。

#include <tuple>
#include <type_traits>


template <typename... Args>
struct Outer {

    struct Inner {
        Inner(const Outer* out, Args... vals) 
            : outer(out)
            , values(vals...)
         {}

         // This ctor should be enabled only if Args are non-empty
         template <typename = std::enable_if_t<(sizeof...(Args) > 0)>>
         Inner(const Outer* out)
            : outer(out)
         {}

        const Outer* outer;
        std::tuple<Args...> values;
    };

};

int main()
{
    Outer<int, int> o1;
    Outer<int, int>::Inner i1(&o1, 1, 2);
    Outer<int, int>::Inner i11(&o1);

    Outer<> o2;
    Outer<>::Inner i2(&o2);
    Outer<>::Inner i21(nullptr);

}

在Godbolt上显示: https ://godbolt.org/z/lsivO9

有趣的部分是结果:

  • GCC 8.2 -std=c++17编译失败
  • GCC trunk -std=c++17确定
  • MSVC 19.14 /std:c++17 /permissive-确定
  • MSVC 19.16 /std:c++17 /permissive-确定
  • clang 7 -std=c++17编译失败
  • clang trunk -std=c++17编译失败

因此,问题是:

  • Outer类的Args...Inner类的直接上下文吗?
  • 上面的例子格式正确吗?
  • 哪个编译器正确?
  • 为什么GCC在树干上开始表现出不同?

您需要使std::enable_if依赖于构造函数模板参数

template <std::size_t N = sizeof...(Args), std::enable_if_t<(N > 0), bool> = true>
Inner(const Outer* out)
: outer(out)
{}
template <typename = std::enable_if_t<(sizeof...(Args) > 0)>>
     Inner(const Outer* out)

Args为空时,这是

template <typename = std::enable_if_t<false>>
     Inner(const Outer* out)

仅当SFINAE依赖于函数的模板参数时,SFINAE才适用于函数。 这里不是。 因此,硬错误是适当的。

在这种情况下,可能不需要诊断,并且程序仍然格式错误(因此编译器可以随意执行任何操作)。 解决这个问题很棘手,并且由于有一个简单的解决方法,因此您最好也这样做。

template <std::size_t N = sizeof...(Args), typename = std::enable_if_t<(N > 0)>>

还是我的首选

template <std::size_t N = sizeof...(Args), std::enable_if_t<(N > 0), bool> = true>

过载时效果更好。

但是,在您的特定情况下,第一个ctor变为第二个:

    Inner(const Outer* out, Args... vals) 
        : outer(out)
        , values(vals...)
     {}

Args...为空时,我在这里看不到要点。

暂无
暂无

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

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