(Извиняюсь за громоздкий заголовок; я не знаю, как более кратко изложить эту проблему. Если у кого-то есть идея получше, пожалуйста, не стесняйтесь редактировать!)
Я хочу написать бесплатную функцию, которая может автоматически определять тип ее параметра на основе возвращаемого значения функции-члена класса. Используя decltype
, эта часть проста.
Я также хочу получить утверждение во время компиляции, чтобы проверить предположение относительно этого типа параметра, и именно здесь мое предлагаемое решение разваливается.
Рассмотрим следующее MCVE:
#include <type_traits>
#include <array>
#include <iostream>
class Foo
{
public:
std::array<int, 10> Get();
};
void PrintFoos(const decltype(Foo().Get())& param)
{
static_assert(param.size() == 10, "wrong size");
for (const auto& i : param)
{
std::cout << i << "\n";
}
}
GCC компилирует вышеуказанный код просто отлично, без предупреждения.
Сланг, с другой стороны, ржет:
error: static_assert expression is not an integral constant expression
static_assert(param.size() == 10, "wrong size");
^~~~~~~~~~~~~~~~~~
Так же, как и MSVC:
(13): error C2131: expression did not evaluate to a constant
(13): note: failure was caused by a read of a variable outside its lifetime
(13): note: see usage of 'param'
Почему GCC компилирует это нормально, когда другие компиляторы отклоняют его? Есть ли у меня расширение GCC для поддержки этого?
Что говорит об этом языковой стандарт? Я нацеливаюсь на C ++ 17, но мне также было бы интересно узнать, есть ли какие-либо изменения по сравнению с C ++ 14.
Бонусный вопрос: Есть ли способ, которым я могу изменить этот код, чтобы он работал? Очевидно, что static_assert
должен завершиться неудачей, если выражение decltype
не соответствует типу std::array
, поскольку функция-член size()
не будет constexpr
. Я полагаю, что есть решение, включающее добавление вспомогательной функции шаблона, но я бы не стал добавлять другое определение функции, если в этом нет крайней необходимости.