Что означает ... (многоточие) как один-единственный параметр функции в прототипе функции в C ++? - PullRequest
3 голосов
/ 01 февраля 2020

Я натолкнулся на объявление функции, например:

int vsa_d(...);

с ... в качестве одного-единственного параметра.

Я знаю, что с помощью многоточия мы можем обратиться к несколько объектов, но к чему здесь относится ...?

  • Что это значит и для чего оно предназначено?

  • Для чего ... вычисляется компилятором?

  • Может ли многоточие использоваться также в качестве аргумента функции при вызове функции?


Я нашел здесь https://en.cppreference.com/w/cpp/language/variadic_arguments в " Notes ":

На языке программирования C, в как минимум один именованный параметр должен стоять перед параметром с многоточием, поэтому printz (...); не является действительным. В C ++ эта форма разрешена, даже если аргументы, передаваемые такой функции, недоступны и обычно используются в качестве резервной перегрузки в SFINAE, используя наименьший приоритет преобразования многоточия в разрешении перегрузки.

Таким образом, он должен использоваться для чего-либо вроде " резервной перегрузки " в " SFINAE ".

Что это значит

Ответы [ 2 ]

3 голосов
/ 01 февраля 2020

Аргумент ... используется в качестве всеобъемлющего в некоторых конструкциях SFINAE.

Вот исключение из ответа top в вопросе о написании черты типа has_helloworld<T> который определяет, имеет ли тип T член helloworld:

template <typename T>
class has_helloworld
{
    typedef char one;
    struct two { char x[2]; };

    template <typename C> static one test( typeof(&C::helloworld) ) ;
    template <typename C> static two test(...);    

public:
    enum { value = sizeof(test<T>(0)) == sizeof(char) };
};

int main(int argc, char *argv[])
{
    std::cout << has_helloworld<Hello>::value << std::endl;
    std::cout << has_helloworld<Generic>::value << std::endl;
    return 0;
}

. Он работает следующим образом: если typeof(&T::helloworld) существует и хорошо сформирован, то на сайте test<T>(0), константа 0 преобразуется в указатель на член (-функцию), и эта перегрузка выбирается. Размер возвращаемого типа равен единице.

Если typeof(&T::helloworld) не существует , то эта перегрузка отсутствует в наборе потенциальной перегрузки, и в качестве перегрузки. Размер возвращаемого типа равен двум.

Перегрузка test(...) имеет приятное свойство: она всегда соответствует наихудшему согласованию с последней выбранной перегрузкой. Это означает, что в таких конструкциях он может служить «запасным вариантом по умолчанию».

2 голосов
/ 01 февраля 2020
int vsa_d(...); // can take any number of arguments

Здесь vsa_d может принимать любое количество аргументов.

Таким образом, он должен использоваться для чего-либо вроде «резервной перегрузки» в «SFINAE».

Что это значит?

Пример:

template <typename T>
struct has_f {
  template <typename U, typename = decltype(std::declval<U&>().f())>
  static std::true_type foo(U);

  static std::false_type foo(...);

  using type = typename decltype(foo(std::declval<T>()))::type;
};

struct a {
  void f(){}
};

Здесь foo имеет две перегрузки:

template <typename U, typename = decltype(std::declval<U&>().f())>
static std::true_type foo(U);

Если выражение decltype(std::declval<U&>().f() допустимо, то, что бы мы ни называли has_f, действительно имеет функцию f, и эта перегрузка будет выбрана.

В противном случае будет выбрана функция-не шаблонный элемент

static std::false_type foo(...);

Потому что он имеет самый низкий приоритет.


Вызов

std::cout << std::boolalpha << has_f<a>::type();

дает

true
...