libc ++is_copy_constructible对我来说似乎是错误的

libc++ is_copy_constructible seems wrong to me

本文关键字:似乎是 错误 对我来说 constructible ++is copy libc      更新时间:2023-10-16

is_copy_constructible的libc++实现是这样的:

template <class _Tp>
struct _LIBCPP_TYPE_VIS_ONLY is_copy_constructible
    : public is_constructible<_Tp, const typename add_lvalue_reference<_Tp>::type>
    {};

is_copy_constructible的C++规范很简单:

std::is_copy_constructible specification: std::is_constructible<T, const T&>::value is true.

但是,上面的实现不是实现 T&const 而不是 const T&吗?将 const 应用于add_lvalue_reference应该没有效果,并且至少有一个编译器 (EDG( 以警告的形式识别这一点。

演示问题的示例程序:

#include <type_traits>
struct ProofTest
{
    ProofTest(){}
    ProofTest(const ProofTest&) = delete;  // is_copy_constructible should use this.
    ProofTest(ProofTest&){ }               // But instead it's using this.
};
void Proof()
{
    static_assert(std::is_copy_constructible<ProofTest>::value == false, "is_copy_constructible bug");
}

在libstdc++下,上面的代码编译正常,但在libc++下,static_assert触发。

以下修复是否正确?

template <class _Tp>
struct _LIBCPP_TYPE_VIS_ONLY is_copy_constructible
    : public is_constructible<_Tp, typename add_lvalue_reference<typename std::add_const<_Tp>::type>::type>
    {};

这也影响了其他几个libc++类型的特征。

同意,感谢您的错误报告。

更新

相关问题:以下各项的预期值是多少: std::is_constructible<int&>::value ?不太清楚 我从阅读标准。

标准说了什么:

对于可引用的类型T,结果与is_constructible<T, const T&>::value相同,否则false

"可引用类型"基本上不是void。 我在解释。 这不是一个确切的定义。 它的意思是可以理解的,而不是精确的。 语言律师(包括我自己(可以把它拆开。 但为了便于理解,"除了void之外的任何东西"已经足够接近了。

所以你的问题变成了,什么是:

std::is_constructible<int&, const (int&)&>::value  // I've used pseudo code

应用于引用const是无操作 ((。 应用于左值引用的左值引用是无操作的(由于引用折叠(。 例如,考虑以下非便携式type_name设施:

#include <type_traits>
#include <memory>
#include <iostream>
#include <cxxabi.h>
#include <cstdlib>
template <typename T>
std::string
type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)(void*)> own
           (
                abi::__cxa_demangle(typeid(TR).name(), nullptr,
                                           nullptr, nullptr),
                std::free
           );
    std::string r = own != nullptr ? own.get() : typeid(TR).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}
int
main()
{
    typedef int& T;
    std::cout << type_name<const T&>() << 'n';
}

对我来说,这打印出来了:

int&

因此,上述内容简化为:

std::is_constructible<int&, int&>::value  // true

这应该回答true因为左值int应该可以从非常量左值int构造。