constexpr несоответствие между gcc8.2 и (intel) icc19.0.1

Следующий код компилируется на gcc 8.2, но не компилируется на icc 19.0.1:

#include <tuple>

template <typename Type, typename... TypeList>
constexpr size_t f(std::tuple<TypeList...> const &){
    return 0;
}

template <typename Type, typename Tuple>
size_t g(Tuple && t){
    static size_t constexpr v= f<Type>(t);
    return v;
}

size_t h(){
    std::tuple<int> tuple;
    return g<int>(tuple);
}

Ошибка, которую я получаю от icc:

error: expression must have a constant value
static size_t constexpr v = f<Type>(t);
                            ^
note: the value of parameter "t" cannot be used as a constant

Компилятор Intel прав в том, что 't' обычно неизвестно и не может использоваться в качестве константы. Однако используется только тип «t», который известен во время компиляции (для определения пакета параметров шаблона «TypeList»).

Почему это разрешено в gcc, но не в icc? Какой компилятор правильный?


person Benny K    schedule 29.01.2019    source источник
comment
clang и msvc также отклоняют этот код.   -  person Holt    schedule 31.01.2019


Ответы (1)


Это не отвечает на мой вопрос о том, кто прав и почему, но вот (чуть менее элегантный) обходной путь, который работает на обоих компиляторах. Буду рад услышать, если кто-нибудь знает лучшее решение.

template <typename Type, typename Tuple, size_t... Indices>
constexpr size_t f(std::index_sequence<Indices...> const &){
    // TypeList is now 'std::tuple_element_t<Indices, TTuple>...'
    return 0;
}
template <typename Type, typename Tuple>
constexpr size_t f(){
    using BareTuple = std::remove_const_t<std::remove_reference_t<Tuple> >;
    return f<Type, BareTuple>
        (std::make_index_sequence<std::tuple_size_v<BareTuple>>{});
}
template <typename Type, typename Tuple>
constexpr size_t g(Tuple && t){
    size_t constexpr occurrences = f<Type, Tuple>();
    return occurrences;
}
...
person Benny K    schedule 31.01.2019