declval的定义基于什么C ++规则?

时间:2018-08-17 05:32:42

标签: c++ metaprogramming template-meta-programming

最近,我想知道如何实现像declval这样的元功能。

我尝试过的第一件事是:

template <typename T>
constexpr auto declval() -> T&&;

这样就很好了,除了当我试图用它来创建varialbe时(我知道现在没有任何意义),我得到了链接器错误,这很明显,因为该函数没有正文

auto varName = declval<int>(); // linker error
decltype(declval<int>()) varName2 = 5; // works fine

尽管如此,原始的实现(从gcc版本开始)是否会以相同的方式表现(给我链接器错误)。事实证明,他们尝试使用declval来创建变量时,其静态断言看起来或多或少像:

static_assert(__declval_protector<T>::stop, "error message");

这令我惊讶。我想实现完全相同的行为。我的第一次尝试是:

template <typename T>
auto declval() -> T&&{static_assert(false, "error message")}

我认为,也许在declval上下文中使用decltype时,根本就不需要它的主体,所以也许编译器会跳过它,如果我试图创建变量,它将做static_assert,因为declval的身体很关键

那不是事实。我总是遇到static_assert错误,无法使用declval编译任何程序。我以为我会尝试以与标准库相同的方式实现它。最后,在同事的帮助下,我们实现了以下实现:

template <typename T>
struct Protector{
    const static bool stop=false;
};

template <typename T>
constexpr auto declval() -> T&&
{
    static_assert(Protector<T>::stop, "You cannot do it");
}

这完全正常。与标准库版本完全相同。但是为什么这样做有效,对我来说完全是个谜。

谁能解释我第二种实现在C ++中如何工作?对我来说,它应该执行与static_assert上下文相同的decltype错误,但显然不会。

实现方式不同的原因是什么。

0 个答案:

没有答案