【问题标题】:std::enable_if not working as expected in Visual Studio 2013std::enable_if 在 Visual Studio 2013 中未按预期工作
【发布时间】:2014-07-07 08:15:59
【问题描述】:

我正在用 C++ 编写一个小型库,我只希望模板在算术类型上进行模板化时被实例化,但我发现了以下问题:

如果我对Foo有以下定义:

template<typename T, typename Enable = void>
class Foo;

template<typename T>
class Foo<T, std::enable_if<std::is_arithmetic<T>::value>::type> {
    Foo() = default;
    Foo( const Foo& ) = default;
    ~Foo() = default;

    template<typename U>
    Foo( std::initializer_list<U> list )
    {
        static_assert(std::is_convertible<U, T>::value, "Must use an initializer list with type convertible to T");

        for( std::size_t s = 0; s < 10; ++s )
        {
            tArray[s] = static_cast<U>(list[s]);
        }
    }

private:
    T       tArray[10];
};

我尝试如下初始化它:

int main()
{
    Foo<int> test{ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} };

    return 0;
}

我收到以下错误:

Foo&lt;T, std::enable_if&lt;std::is_arithmetic&lt;T&gt;::value&gt;::type&gt;::Foo( std::initializer_list&lt;U&gt; ) [with T=int, U=int] 无法访问

我不熟悉在 TMP 中使用 std::enable_if,但根据 cppreference.com 看来,这应该可以工作。我在这里缺少什么,或者这是 VS2013 的错误?

【问题讨论】:

  • 一般元提示:如果您要问“或者它是编译器中的错误”,它不是。
  • @KerrekSB 这是一个很好的建议,但在 msvc 的情况下,它完全是一个错误,如果我们在谈论模板,则更多
  • @KerrekSB 确实,通常情况下我犯了一个愚蠢的错误;然而,并非总是如此(参见this
  • @Shaktal: 可能是这样,但如果你认为你发现了一个合法的错误,我希望你努力制作一个 minimal 测试用例错误,只有错误,并与其他编译器交叉检查。我知道存在错误;我的元提示是针对一个特定的种类问题——这个问题提出了一个大的、非结构化的代码转储并说“这不起作用,它是一个编译器错误”......
  • @Shaktal:进一步澄清这一点:answer 是“这是一个编译器错误”是完全正常的。但这不会也不应该是提问者的怀疑。如果是这样,提问者应该缩小问题范围,以确定它是一个错误(见上文)或忽略该选项。

标签: c++ templates c++11 template-meta-programming enable-if


【解决方案1】:

你的初始化器被声明为私有的。将其声明为公开。并且在使用std::enable_if&lt;&gt;::type时不要忘记添加typename

编辑:std::initializer_list 中没有下标重载。

template<typename T, typename Enable = void>
class Foo;

template<typename T>
class Foo<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {

public:
    Foo() = default;
    Foo( const Foo& ) = default;
    ~Foo() = default;

    template<typename U>
    Foo( std::initializer_list<U> list )
    {
        static_assert(std::is_convertible<U, T>::value, "Must use an initializer list with type convertible to T");

        for( std::size_t s = 0; s < 10; ++s )
        {
            // ERROR
            // tArray[s] = static_cast<U>(list[s]);
        }
    }

private:
    T       tArray[10];
};

【讨论】:

    【解决方案2】:

    这与enable_if 无关。您在课程开始时没有指定任何成员访问控制,默认情况下 class 成员(与 struct 成员相反)是 private。只需将public: 放在您的班级成员声明之前。

    【讨论】:

    • sigh 原来如此!!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 2017-08-06
    相关资源
    最近更新 更多