【发布时间】:2019-03-07 22:51:56
【问题描述】:
最近我试图检测特定私有构造函数的存在并遇到std::is_constructible 仅检查直接上下文因此无法识别任何此类构造函数的问题。经过一番研究,我确实看到一个答案 here 提到正确的方法是与 std::is_constructible 成为有问题的类的朋友,以允许它访问。
为了测试这个方法是否有效,我尝试了以下测试代码
#include <type_traits>
class A {
private:
template<typename, typename ...>
friend struct std::is_constructible;
A() = default;
};
int main() {
static_assert(std::is_constructible<A>::value);
static_assert(std::is_constructible_v<A>);
}
有趣的是,这种方法似乎确实适用于 Visual Studio 2017 中的 std::is_constructible,尽管我随后开始遇到 std::is_constructible_v 的问题。在他们的实现中,他们没有对实际结构 std::is_constructible 本身使用别名模板,而是直接调用内部使用的内部函数,这反过来又忽略了朋友声明。
认为这是他们的标准库实现的错误,然后我在其他编译器中进行了测试,发现无论是 clang 还是 gcc 在任何情况下都无法通过此断言,这让我怀疑它是否应该像这样工作这一点都没有(链接帖子上的一些 cmets 似乎暗示这是一个错误,而其他人则说它不应该考虑朋友声明)。
因此,主要问题是该代码是否可以正常工作(如它是否应该能够访问私有构造函数并传递断言),而标准定义的访问仅限于即时上下文? here 也提出了类似的问题,我不确定的主要是在这种情况下“直接上下文”的确切定义,因为这与链接问题中的示例略有不同。
来自 N4713 23.15.4.3.8 [meta.unary.prop]/8 的相关段落:
访问检查是在与 T 和任何无关的上下文中执行的 的Args。只有直接上下文的有效性 考虑变量初始化。
【问题讨论】:
-
大部分情况下,
friend struct std::is_constructible;不能保证通过您的任何断言。
标签: c++ language-lawyer c++17 typetraits