【问题标题】:libc++ is_copy_constructible seems wrong to melibc++ is_copy_constructible 对我来说似乎是错误的
【发布时间】:2013-11-19 01:50:04
【问题描述】:

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++ 类型特征。

【问题讨论】:

    标签: c++ c++11 typetraits libc++


    【解决方案1】:

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

    更新

    相关问题:预期值是多少: std::is_constructible&lt;int&amp;&gt;::value?目前还不是很清楚 我从阅读标准。

    标准是怎么说的:

    对于可引用类型T,结果与is_constructible&lt;T, const T&amp;&gt;::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 应该可以从非 const 左值 int 构造。

    【讨论】:

    • @Tony:回答、评论和开发者回复合二为一!
    • 相关问题:std::is_copy_constructible::value 的期望值是多少?阅读标准对我来说并不是很清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多