SFINAE 使用 decltype() 忽略 Visual Studio 2012 上的"private"

SFINAE using decltype() ignores "private" on Visual Studio 2012

本文关键字:Studio 2012 上的 Visual private 忽略 使用 decltype SFINAE      更新时间:2023-10-16

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

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(表达式)推导出的东西(去掉了顶级引用,这样我就可以始终声明指向该类型的指针),另一个是使用"…"——通常对我写的其他类似类型特征非常有效。

但对于这个,我有一个问题。Visual Studio 2012抱怨最后一个static_assert,声称PrivateBean类型的元函数值应该为true,尽管有类似的代码

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

不编译,原因很明显:

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

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

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

UPD:

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

但仍然有一个问题:Visual Studio 2012可以做些什么变通方法来使这种类型的特性在那里正确工作?

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