使用参数类型的值在尾随返回中是否需要decltype

时间:2018-11-16 20:09:19

标签: c++ templates language-lawyer c++17

在试图理解c ++ 17兼容代码时,我对以下代码感到困惑 该函数使用值中来自integrate_constant类型参数的值 尾随返回类型。 (请随时纠正我的术语,尝试学习)

下面显示了两个简单的版本,在版本上带有和不带有decltype。 尾随返回中的参数。

使用编译器资源管理器https://godbolt.org/z/vqmzhu

第一个(bool_from1)可以正常编译
MSVC 15.8; / std:c ++ 17,/ O2,/ permissive-
和clang 8.7.0.0和gcc 8.2; -std = c ++ 17,-O2,-pedantic
具有正确的汇编器输出

第二个(bool_from2)错误出现在gcc上, 它还显示了VS中的Intellisense错误,但编译时没有错误。

我在cppreference或标准草稿中找不到任何内容,这向我表明,遵循代码需要decltype(atype),但是... ???

我的问题是所需的decltype。 我的编译器标志是否正确用于c ++ 17一致性检查。

代码:

#include <utility>

namespace ns {
volatile bool vb;

template<bool B> struct bool_ : std::bool_constant<B> {};

// using decltype(btype) in trailing return compiles in all 3
template<typename Bool> constexpr auto bool_from1(Bool btype)
-> bool_<decltype(btype)::value> {
    return bool_<btype.value>{};
}
void test1() {
    static_assert( // simple test
        bool_from1(std::true_type{}).value
        );
    vb = bool_from1(std::true_type{}).value; // check output
}

// without decltype in trailing return compile in VS and clang
// but errors out in gcc; and VS shows Intelisense errors but compiles
template<typename Bool>
constexpr auto bool_from2(Bool btype)
// ^ gcc 8.2 error: deduced class type 'bool_' in function return type
-> bool_<btype.value> {
    // ^ gcc: invalid template-id; use of paramter outside function body before '.'
    //^ VS Intellisense on btype: <error-constant>; a paramter is not allowed
    return bool_<btype.value>{};
}

void test2() {
    static_assert(
        bool_from2(std::true_type{}).value
        //^ gcc: bool_from1 was not declared in this scope
        );
    vb = bool_from2(std::true_type{}).value; // check output
}
}

1 个答案:

答案 0 :(得分:1)

这看起来像是gcc错误,bug report: "Trailing return types" with "non-type template arguments" which could be "constant expressions" produce a parsing error似乎适合这种情况:

  

请考虑以下代码段:

template <int>
struct bar {};

template <class I>
auto foo(I i) -> bar<i()> { return {}; }

int main()
{
    foo([]{ return 1; }); // (0)
}
     

这可以按clang ++ 5的要求进行编译和工作,但是会产生一个   g ++ 7上的编译时错误:

prog.cc:5:25: error: template argument 1 is invalid
auto foo(I i) -> bar<i()> { return {}; }