c – T declval()而不是common_type的T \u0026\u0026 declval()

使用在表单中声明的​​std :: declval不是更好吗:

template< class T > T declval(); // (1)

当前的一个:

template< class T > T && declval(); // (2)

对于std :: common_type(可能只为当前目的使用不同的名称)?

使用(1)的common_type的行为比使用(2)时的行为更接近三元运算符(但不使用std :: decay_t)的行为:

template< typename T >
T declval();

template <class ...T> struct common_type;

template< class... T >
using common_type_t = typename common_type<T...>::type;

template <class T>
struct common_type<T> {
    typedef T type;
};

template <class T, class U>
struct common_type<T, U> {
    typedef decltype(true ? declval<T>() : declval<U>()) type;
};

template <class T, class U, class... V>
struct common_type<T, U, V...> {
    typedef common_type_t<common_type_t<T, U>, V...> type;
};

#include <type_traits>
#include <utility>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunevaluated-expression"
int
main()
{
    int i{};
    static_assert(std::is_same< int &, decltype((i)) >{});
    static_assert(std::is_same< int  , std::common_type_t< decltype((i)), decltype((i)) > >{}); 
    static_assert(std::is_same< int &, decltype(true ? i : i) >{});
    static_assert(std::is_same< int &, common_type_t< decltype((i)), decltype((i)) > >{});

    int && k{};
    static_assert(std::is_same< int &&, decltype(k) >{});
    static_assert(std::is_same< int   , std::common_type_t< decltype(k), decltype(k) > >{}); 
    static_assert(std::is_same< int &&, decltype(true ? std::move(k) : std::move(k)) >{}); 
    static_assert(std::is_same< int &&, common_type_t< decltype(k), decltype(k) > >{});
    return 0;
}
#pragma clang diagnostic pop

Live example.

这种方法的缺点是什么?是否为真,对于(1)在decltype()中,上下文类型T应该是可构造的(根本应该至少有一个构造函数)和/或可破坏?

Reference article说:

For non-specialized std::common_type, the rules for determining the common type between every pair T1, T2 are exactly the rules for determining the return type of the ternary conditional operator in unevaluated context, with arbitrary first argument of type bool and with xvalues of type T1 and T2 (since C++17) std::declval<T1>() and std::declval<T2>() (until C++17) as the second and the third operands. The common type is the result of std::decay applied to the type of the ternary conditional (since C++14).

我认为最后一句话(强调)很可能不仅仅是因为C 14,而且直到C 17才公平.否则,即使在C17之后,第一句引用也不会成立,并且会出现一些缺陷.

关于std :: common_type问题的should-stdcommon-type-use-stddecay评论中有一些澄清,但它只是当前问题的背景信息.

最佳答案 优点:

template <class T> T&& declval();

它适用于任何类型T,而简单地返回T将不适用于不可返回的类型(例如函数,数组)和不可销毁的类型(例如私有/受保护/删除的析构函数,抽象基类).

当然,令人不快的是common_type< int,int>最终成为int&&,然后你需要添加decay,这使得common_type< int&,int&>是int – 这也没有意义.这里没有胜利.

最终,我认为我们只需要一些语言功能,在未评估的环境中,“给我一些类型T”,适用于任何T,这真的给你一个T(而不是T&&).

点赞