c – 为什么我可以在decltype()中使用私有默认构造函数?

看看代码:

#include <iostream>
#include <utility>

class test
{
private:
    test() { }
public:
    test foo() { return *this; }

    static const char *name() { return "test"; }
};

int main()
{
    std::cout << decltype(test().foo())::name() << std::endl;               // 1
    std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2
}

我期望// 1行无法编译,因为test的默认构造函数是private.

However, it works well.我在我的g 4.8.3上测试了它–Wall -Wextra -Werror -pedantic难以置信,但它运行良好,没有任何错误或警告.

(此外,它似乎也适用于GCC 4.9.1.)

this page开始,如果表达式未被评估,我想我们可以使用私有默认构造函数.所以,我测试了以下内容来检查它.

#include <iostream>
#include <utility>

class test
{
private:
    test(int) { }
public:
    test foo() { return *this; }

    static const char *name() { return "test"; }
};

int main()
{
    std::cout << decltype(test().foo())::name() << std::endl;               // 1
    std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2
}

(live example)

正如所料,它没有编译.

但为什么??怎么可能?我们可以在未评估的表达中使用私人成员吗?或者默认构造函数是否有特殊规则?你能解释一下为什么吗?

它不应该编译. C 11 [class.temporary]有关于创建临时对象的说法:

12.2/1 Even when the creation of the temporary object is unevaluated
or otherwise avoided, all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. [ Note: even if there is no call to the destructor or copy/move constructor, all the semantic restrictions, such as accessibility and whether the function is deleted, shall be satisfied. However, in the special case of a function call used as the operand of a decltype-specifier, no temporary is introduced, so the foregoing does not apply to the prvalue of any such function call. — end note ]

因此,即使未经评估,您仍然受限于创建和销毁临时所需的任何函数(包括构造函数)的可访问性.该注释的最后一句澄清了像declval这样的函数可以用来避免这个障碍.

相关文章
相关标签/搜索