c++ - T declval() 而不是 T && declval() for common_type

标签 c++ c++11 c++14 typetraits c++17

std::declval不是更好吗?声明形式:

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

然后是当前的:

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

std::common_type (可能仅出于当前目的使用不同的名称)?

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

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).

我认为最后一句 ( emphasized ) 很可能不应该只是 since C++14还有until C++17公平起见。否则,即使在 C++17 之后,引用的第一句也不会成立,并且会出现一些缺陷。

should-stdcommon-type-use-stddecay 中有一些说明关于 std::common_type 的评论问题,但这只是当前问题的背景信息。

最佳答案

优势:

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

它是否适用于任何类型 T ,而只是返回 T不适用于不可返回的类型(例如函数、数组)和不可破坏的类型(例如私有(private)/ protected /删除的析构函数、抽象基类)。

当然,缺点是common_type<int, int>最终成为 int&& , 然后你需要添加 decay这使得 common_type<int&, int&>int - 这也没有意义。这里没有胜利。


最终,我认为我们只需要一些语言功能,在未评估的上下文中,“给我一些 T 类型的东西”适用于任何 T ,那真的给了你一个T (而不是 T&& )。

关于c++ - T declval() 而不是 T && declval() for common_type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35525912/

相关文章:

c++ - 自定义元素的迭代器在 vector 中

c++ - 与模板参数解耦,无需动态多态性

c++ - 如何从 C++ 程序中的容器类中删除第一个元素?

c++ - 为什么这段代码会出现 "exception spec is more lax than base"错误?

c++ - 使用 std::vector<> 和 std::shared_ptr<> 会导致错误

c++ - 如果未实例化成员模板,是否要评估 static_asserts?

c++ - 尽管在 Linux 内核版本 4.5 下,gRPC(C Base) 轮询引擎仍使用 'epollex' 构建

c++ - 如何使用对象的指针调用对象的成员函数?

c++ - 在 C++11 中使用 auto

c++ - 友元函数默认模板 : Intel ICPC warning