加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 03:07:24 所属栏目:百科 来源:网络整理
导读:iscopy_constructible的libc实现是这样的: template class _Tpstruct _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_con
iscopy_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类型的特征.

解决方法

同意,谢谢你的错误报告.

更新

Related question: What’s the expected value of:
std::is_constructible<int&>::value? It’s not perfectly clear to
me from reading the standard.

标准说明:

For a referenceable type T,the same result as is_constructible<T,const T&>::value,otherwise false.

“可引用类型”基本上是一个空白.我是释义这不是一个确切的定义.这是可以理解的,而不是精确的.语言律师(包括我自己)可以将它分开.但是为了方便理解,“除了一个空白之外的任何东西”都足够近了.

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

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

const应用于引用是一个no-op().而应用于lvalue引用的lvalue引用是一个no-op(由于引用崩溃).例如考虑这个非便携式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),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

这应该是真的,因为lvalue int应该是从非const lvalue int可以构造的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读