«Если constexpr» в C ++ 17 не работает в не шаблонной функции - PullRequest
0 голосов
/ 26 апреля 2018

Я пытался играть по стандарту C ++ 17. Я пытался использовать одну из функций C ++ 17 if constexpr. И у меня возникла проблема ... Пожалуйста, посмотрите на следующий код. Это компилируется без ошибок. В следующем коде я попытался использовать if constexpr, чтобы проверить, является ли это указателем.

#include <iostream>
#include <type_traits>

template <typename T>
void print(T value)
{
  if constexpr (std::is_pointer_v<decltype(value)>)
    std::cout << "Ptr to " << *value << std::endl; // Ok
  else
    std::cout << "Ref to " << value << std::endl;
}

int main()
{
  auto n = 1000;
  print(n);
  print(&n);
}

Но когда я переписываю приведенный выше код, как показано ниже, где if constexpr находится в функции main:

#include <iostream>
#include <type_traits>

int main()
{
  auto value = 100;
  if constexpr (std::is_pointer_v<decltype(value)>)
    std::cout << "Ptr to " << *value << std::endl; // Error
  else
    std::cout << "Ref to " << value << std::endl;
}

Я получаю ошибку компиляции:

main.cpp:8:32: error: invalid type argument of unary ‘*’ (have ‘int’) 
std::cout << "Ptr to " << *value << std::endl;

Проблема не в основной функции. Это может быть любая функция, подобная следующей.

void print()
{
  auto value = 100;
  if constexpr (std::is_pointer_v<decltype(value)>)
    std::cout << "Ptr to " << *value << std::endl; // Error
  else
    std::cout << "Ref to " << value << std::endl;
}

int main()
{
  print();
}

Я хотел бы знать, почему if constexpr работает только в шаблонных функциях, даже если тип определяется типом decltype из входного параметра.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

C ++ стандарт, пункт 9.4.1:

Если оператор if имеет форму if constexpr, значение условия должно быть контекстно-преобразованным константным выражением типа bool (8.6); эта форма называется оператором constexpr. Если значение преобразовано условие ложно, первое подзаголовок является отклоненным оператором, в противном случае второе подзаголовок, если имеется, является отброшенным оператором. Во время создания экземпляра вмещающей шаблонной сущности (раздел 17), если условие не зависит от значения после его создания, исключенное подзаголовок (если есть) не создается.

(акцент мой)

Итак, подстановка constexpr if по-прежнему создается, если она не находится внутри шаблона, поэтому она должна хотя бы компилироваться.

0 голосов
/ 27 апреля 2018

Я хотел бы знать, почему «if constexpr» работает только в шаблонных функциях, даже если тип определяется decltype из входного параметра.

Это по замыслу.

if constexpr не будет создавать экземпляр ветвь, не занятая, если она находится внутри шаблона . Он не просто будет относиться к ветке, которую не воспринимают как суп-лексем, и не будет разбирать ее или выполнять полностью семантический анализ. Обе стороны все еще будут анализироваться, и поскольку *value плохо сформирован в течение int s, это ошибка.

Вы просто не можете использовать if constexpr, чтобы избежать компиляции не шаблонного кода. Это только для того, чтобы избежать создания экземпляра кода шаблона, который потенциально недопустим для конкретной специализации.

...