Какой правильный шаблонный параметр / аргумент для оператора [] в качестве функции-члена? - PullRequest
2 голосов
/ 10 мая 2019

При попытке вызвать шаблон функции, который принимает тип и параметр / аргумент этого типа в качестве параметров / аргументов шаблона, компилятор выдает ошибку, которая не создается с аналогичными параметрами / аргументами.Поэтому мне было интересно, каковы правильные параметры / аргументы в случае вызова шаблонов функций для функции-члена "operator [] const" векторного класса!

Рассмотрим этот фрагмент кода:

class test_class{
    public:
    int member;
    int& operator[](size_t) {return member;}
    const int& operator[](size_t) const{return member;}
};
typedef std::vector<int> vector_type;

typedef const int&(test_class::* OK_type)(size_t)const;
typedef const int&(vector_type::* not_OK_type)(size_t)const;

static constexpr OK_type OK_pointer = &test_class::operator[];
static constexpr not_OK_type not_OK_pointer = &vector_type::operator[];

template<typename t__, t__>
void function(){}

С кодом выше все в порядке, теперь рассмотрим основную функцию:

int main() {
    function<OK_type, OK_pointer>();
    function<not_OK_type, not_OK_pointer>();
    return 0;
}

Первый вызов шаблона функции в порядкено не второй.Ошибка, которую выдает компилятор:

error: no matching function for call to ‘function<not_OK_type, not_OK_pointer>()’
note: candidate: ‘template<class t__, t__ <anonymous> > void function()’
note:   template argument deduction/substitution failed:
error: ‘const int& (std::vector<int>::*)(size_t) const{((const int& (std::vector<int>::*)(size_t) const)std::vector<int>::operator[]), 0}’ is not a valid template argument for type ‘const int& (std::vector<int>::*)(long unsigned int) const’
function<not_OK_type, not_OK_pointer>();
note: it must be a pointer-to-member of the form ‘&X::Y’

Интересно, что даже если шаблон функции был сформирован как:

template<auto>
void function(){}

, это привело бы к тому же результату.

Я должендобавьте, что в случае неконстантной версии ошибка такая же (для std::vector).

Поэтому мне интересно

A: что не так?

B: Учитывая, что при несоответствии not_OK_type и &vector_type::operator[] компилятор также выдавал бы ошибку в случае:

static constexpr not_OK_type not_OK_pointer = &vector_type::operator[];

Есть ли разница между типами, которые можно использовать как constexpr?и тип, который может быть использован в качестве параметра / аргумента шаблона?

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

Проблема typedef const int&(vector_type::* not_OK_type)(size_t)const;.

Если вы видите stl_vector.h ( здесь ), оператор [] объявляется как noexcept в строке 1040.

Но в объявлении not_OK_type переменной noexcept нет. Вот почему компилятор жалуется.

Чтобы избавиться от ошибки компиляции, добавьте noexcept в not_OK_type переменную. Как это:

typedef const int&(vector_type::* not_OK_type)(size_t)const noexcept;

Рабочий код:

#include <vector>

class test_class{
    public:
    int member;
    int& operator[](size_t) {return member;}
    const int& operator[](size_t) const{return member;}
};
typedef std::vector<int> vector_type;

typedef const int&(test_class::* OK_type)(size_t)const;
typedef const int&(vector_type::* not_OK_type)(size_t)const noexcept;

static constexpr OK_type OK_pointer = &test_class::operator[];
static constexpr not_OK_type not_OK_pointer = &vector_type::operator[];

template<typename t__, t__>
void function(){}

int main() {
    function<OK_type, OK_pointer>();
    function<not_OK_type, not_OK_pointer>();
    return 0;
}
0 голосов
/ 10 мая 2019

@ Кунал Пури дал правильный ответ на раздел А. вопроса.

Что касается раздела B вопроса, я думаю, ключ может быть найден в одном исключении , которое применяется, когда преобразованное константное выражение используется в качестве аргумента шаблона для нетипового шаблона параметр.

Согласно (https://en.cppreference.com/w/cpp/language/constant_expression), преобразованное константное выражение при определенных условиях и, в частности, в случае преобразование указателя на функцию noexcept в указатель на функцию является константным выражением. Это объясняет, почему компилятор сделал не выдает ошибку в случае:

static constexpr not_OK_type not_OK_pointer = &vector_type::operator[];

Однако согласно (https://en.cppreference.com/w/cpp/language/template_parameters), этот тип преобразованного константного выражения нельзя использовать в качестве указателя на нестатические члены-данные (и, возможно, также на указатель на нестатические функции-члены) для нетипичного параметр шаблона.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...