c++ - 使用 decltype() 的 SFINAE 在 Visual Studio 2012 上忽略 "private"

标签 c++ visual-studio-2012 sfinae typetraits decltype

我正在尝试创建一个元函数,它将告诉我类型 T 是否可以在 bool 上下文中使用,即是否像这样的代码

decltype(T) x = /* ... */;
if (x) { /* ... */ }

将编译。

我使用了一些 C++11 功能,但仅限于 VS 2012 中可用的功能,因为我希望我的代码也能在那里工作。

这是我的代码:

#include <type_traits> // want to use remove_reference and declval from std library

// objects of this type can be used in a boolean context
class AlmostBoolean
{
public:
    operator bool() const { return true; }
};

// should not be used in a boolean context because it requires two user-defined conversions
class RequiresTwoConversions
{
public:
    operator AlmostBoolean() const { return AlmostBoolean(); }
};

// should not be used in a boolean context because the conversion operator is private
class PrivateBoolean
{
private:
    operator bool() const { return true; }
};

namespace kinda_sorta_type_traits
{
    typedef char(&yes_type)[1];
    typedef char(&no_type) [2];

    using std::remove_reference;
    using std::declval;

    template<typename T>
    struct can_be_used_in_a_boolean_context
    {
        template<typename U>
        static yes_type test(typename remove_reference
                             <
                                 decltype( static_cast<bool>(declval<const U &>()) )
                             >::type *);

        template<typename>
        static no_type test(...);

        static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes_type);
    };
}

using kinda_sorta_type_traits::can_be_used_in_a_boolean_context;

static_assert(   can_be_used_in_a_boolean_context< bool                     >::value, "");
static_assert(   can_be_used_in_a_boolean_context< bool &                   >::value, "");
static_assert(   can_be_used_in_a_boolean_context< int                      >::value, "");
static_assert(   can_be_used_in_a_boolean_context< const volatile int &     >::value, "");
static_assert(   can_be_used_in_a_boolean_context< AlmostBoolean            >::value, "");
static_assert(   can_be_used_in_a_boolean_context< AlmostBoolean &          >::value, "");
static_assert( ! can_be_used_in_a_boolean_context< RequiresTwoConversions   >::value, "");
static_assert( ! can_be_used_in_a_boolean_context< RequiresTwoConversions & >::value, "");
//#ifndef _MSC_VER
static_assert( ! can_be_used_in_a_boolean_context< PrivateBoolean           >::value, "");
//#endif

int main()
{
}

这种方法有两个静态 test() 函数的重载——一个采用指向从 decltype(expression) 推导出的东西的指针(顶级引用被剥离以便我总是可以声明一个指向该类型的指针),另一个一个采用“...”——通常对我写的其他类似类型特征非常有效。

但是对于这个,我有一个问题。 Visual Studio 2012 提示最后一个 static_assert,声称 PrivateBoolean 类型的元函数值应该为真,尽管有这样的代码

int main()
{
    PrivateBoolean x;
    if (x) {
    }
}

不编译,原因很明显:

error: C2248: 'PrivateBoolean::operator bool' : cannot access private member declared in class 'PrivateBoolean'

我还在 GCC 4.9.1 上测试了这段代码,它在那里工作得很好。

这是 MSVC 编译器中的错误,还是我的推理有误?

更新:

在 Visual Studio 2015 上检查了完全相同的代码。该错误(我相信它实际上是一个错误)已得到修复。没有错误。只有 IntelliSense 仍然提示这个 static_assert 应该失败,但与原来的问题相比这没什么大不了的:)

但仍然存在一个问题:可以为 Visual Studio 2012 采取什么解决方法来使这种类型特征在那里正常工作?

最佳答案

听起来很有道理,这是一个 Visual Studio 2012 错误。

关于c++ - 使用 decltype() 的 SFINAE 在 Visual Studio 2012 上忽略 "private",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34227773/

相关文章:

c++ - 如何安装 OpenCV 3.3.1。跟踪 API (Ubuntu 16.04)

entity-framework - .net Entity Framework T4 模板在升级到 VS 2012 后无法构建/工作

c++ - 等待 Win32 应用程序中的特定键

c++ - SFINAE比赛未按预期进行

c++ - 部分外部链接

c++ - 无法增加 C++ 程序中的数字范围

c++ - 在 C++ 中编码/解码 URL

c++ - std::list 提示缺少第二个模板参数(分配器)

c++ - 用部分实例化的祖先类替换完全实例化的类

c++ - 将枚举值与 SFINAE 结合使用