#c #operator-overloading
#c #перегрузка оператора
Вопрос:
Я переопределил operator|
действовать как фильтр для заданного vector
и функции, если эта функция возвращает a bool
. В случае, если этого не происходит, он вызывает for_each
vector
.
template<typename T, typename Func>
auto operator | (const vector<T> amp;v, Func f){
bool result = is_same<bool, decltype(f(v[0]))>::value;
vector<T> temp;
if (result){
temp.reserve(v.size());
for(auto itr = v.begin(); itr != v.end(); itr){
bool func_return = f(*itr);
if (func_return){
temp.push_back(*itr);
}
}
return temp;
}
else{
for_each(v.begin(),v.end(),f);
return temp;
}
}
Этот код отлично работает, когда действует как фильтр, но for_each
часть не работает. Всякий раз, когда я пытаюсь запустить следующий код:
int main() {
vector<int> v1 = { 2, 9, 8, 8, 7, 4 };
v1 | []( int x ) { return x % 2 == 0; } | [] ( int x ) { cout << x << " "; };
}
Компилятор возвращает:
error: cannot initialize a variable of type 'bool' with an rvalue of type 'void'
bool func_return = f(*itr);
in instantiation of function template
specialization 'operator|<int, (lambda at
main.cpp:44:43)>' requested here
v1 | []( int x ) { return x % 2 == 0; } | [] ( int x ) { cou...
^
Что кажется мне странным, в конце концов, компилятор не должен выполнять эту строку во втором операторе, как result
и должно быть false
. Кто-нибудь может мне помочь в этом?
Комментарии:
1. Компилятор компилирует ветви if и else. Вы должны использовать
if constexpr
и C 17.2.
if constexpr
возникнет проблема, котораяv[0]
не известна во время компиляции. Какой способ проверить во время компиляции, чтоFunc
это за функция, которая принимает aT
в качестве аргумента и возвращает abool
? Какое-то сравнение с anstd::function
?3. Или… Я думаю, нам на самом деле не нужно знать
v[0]
во время компиляции, потому что для полученияdecltype
нам просто нужно знать типv
, подписьvector<T>::operator[]
и подписьf::operator()
, которые все известны во время компиляции. Значит ли это, что оно работает даже с пустым вектором?4. @NathanPierson Да, с пустым вектором проблем нет.
v[42]
было бы то же самое,v[0]
что и внутриdecltype
.
Ответ №1:
Это лямбда:
[] ( int x ) { cout << x << " "; }
имеет void
возвращаемый тип, поэтому эта строка:
bool func_return = f(*itr);
не компилируется. Поскольку значение result
зависит только от Func
и T
, у вас есть необходимая информация, чтобы решить, выполнять ли if
ветку во время компиляции. Вы можете использовать a constexpr if
вместо времени выполнения if
:
if constexpr(result)
и теперь код внутри этой ветви не будет скомпилирован, когда функция создается с неправильными типами.
Кроме того, вам нужно сделать result
время компиляции постоянным, чтобы использовать его в if constexpr
условии.
Вот демонстрация.