Clang, MSVC, GCC disagree about compiling this code with function application in index_sequence
Asked Answered
D

1

7

This code is from an answer to another question:

template <typename F, std::size_t ... Is>
constexpr auto apply(F f, std::index_sequence<Is...>)
-> std::index_sequence<f(Is)...>
{
    return {};
}

gcc fails with

<source>:5:29: error: expected parameter pack before '...'

msvc and clang compile it.

Changing it to this now causes msvc to fail:

template <typename F, std::size_t ... Is>
constexpr auto apply(F , std::index_sequence<Is...>)
-> std::index_sequence<F{}(Is)...>
{
    return {};
}
<source>(5): error C2187: syntax error: '<end Parse>' was unexpected here 
<source>(5): error C2059: syntax error: '('
<source>(6): error C2988: unrecognizable template declaration/definition 
<source>(6): error C2059: syntax error: '{'
<source>(6): error C2143: syntax error: missing ';' before '{''
<source>(6): error C2447: '{': missing function header (old-style formal list?)

Is this something vague in C++ standard or just an implementation bug? I see no reason why function calls should not be allowed at this place, same for construction of a F{}.

Droshky answered 7/10, 2021 at 22:50 Comment(4)
@xskxzr you need #include <cstddef> #include <utility>Extempore
In case if you want to make it work: godbolt.org/z/dz5rdKnsTBagdad
Considering that f(Is) is a template argument in a template-argument-list and according to temp.variadic#5.7, this should be a valid pack expansion.Hagan
How about clang, btw?Bi
P
0
  1. This code is from 김선달's comment above :
#include <utility>
#include <type_traits>

template<typename F, typename Seq>
struct apply_impl;

template<typename F, std::size_t... Is>
struct apply_impl<F, std::index_sequence<Is...>> {
  private:
    static constexpr auto test(F, std::index_sequence<Is...>)
    -> decltype(std::index_sequence< F{}(Is)... > {});
  public:
    using type = decltype(test(F{}, std::index_sequence<Is...>{}));
};

template<typename F, typename Seq>
using apply = typename apply_impl<F, Seq>::type;

constexpr auto f = [](auto x) -> std::size_t { return x*x; };

using res_type = apply<decltype(f), std::index_sequence<0, 1, 2, 3, 4> >;

static_assert(std::is_same<res_type, std::index_sequence<0, 1, 4, 9, 16>>::value);
  1. And this is from Mechap's comment above

    In a template-argument-list ([temp.arg]); the pattern is a template-argument. From docs

Note: Provide solution as an answer instead of a comment.

Parry answered 20/10, 2021 at 11:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.