• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Can I Simplify Variadic Template Method Calls in C++?

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155
Introduction


If you're working with variadic templates in C++, you might find the need to call methods from base classes within a derived class. This involves invoking the same method name but potentially returning a different pointer depending on which base class is present. In your case, you are using a lambda function to execute this logic. Here, we will explore how to streamline the syntax of your D::onMethod() function while achieving the same functionality without using a lambda.

Understanding the Problem


In your original code, the derived class D inherits from multiple base classes specified in the variadic template. Each base class has an onMethod() that returns a pointer to the Ret object. You want to call onMethod() for each of the base classes and return the first non-null result from the Base class, or nullptr if Base is not among the bases.

While your existing implementation works perfectly, it uses a lambda function to encapsulate the call to onMethod() for each base class in the fold expression. We can improve the syntax by directly invoking onMethod() without the additional complexity of a lambda.

Simplifying D::onMethod() with Fold Expression


Let's refactor the onMethod() function without using lambda expressions. We'll take advantage of fold expressions in C++17 like you have but write it in a cleaner way. Here's how:

Updated Code Example


#include <iostream>
#include <type_traits>

struct Ret {
};

struct B1 {
Ret* onMethod() {
std::cerr << "B1\n";
return nullptr;
}
};

struct B2 {
Ret* onMethod() {
std::cerr << "B2\n";
return nullptr;
}
};

struct Base {
Ret* onMethod() {
std::cerr << "Base\n";
return new Ret();
}
};

template<typename... Bases>
struct D : public Bases... {
Ret* onMethod() {
Ret* result = nullptr;
((result == nullptr) ? (result = Bases::onMethod()) : result, ...);
return result;
}
};

int main(void) {
D<B1, B2, Base> d;
auto* r = d.onMethod();
std::cerr << (r == nullptr) << std::endl;
D<B1, B2> d1;
auto r1 = d1.onMethod();
std::cerr << (r1 == nullptr) << std::endl;
return 0;
}

Explanation of Changes


In the simplified version of D::onMethod(), we replace the lambda with a straight use of a comma operator. The new line creates a sequence that evaluates each base class's onMethod() call. If the result is nullptr, it attempts to call the next base class's onMethod(). When a non-null pointer is returned, it stops evaluating further calls because we short-circuit using the logical short-circuiting behavior. This maintains performance by avoiding unnecessary calls to methods of classes that are not needed.

Benefits of The New Syntax

  • Readability: The new syntax is easier to read at a glance without additional lambda function noise.
  • Familiarity: Developers may find using the comma operator more familiar when encountering this pattern.
  • Clarity: It shines a light on the logic flow, explicitly returning the first valid pointer.
Conclusion


In conclusion, simplifying the method call in your variadic template D class not only improves readability but can also streamline your code's logic flow. This adjustment keeps the functionality intact while ensuring it aligns more closely with common C++ idioms. As always, ensure the bases are designed as expected to avoid undefined behavior. Happy coding!

Frequently Asked Questions

Is this change backward compatible?


Yes, the change preserves the original functionality while simplifying the syntactic structure of the code.

Can I extend it for more complex logic in each base class?


Absolutely! You can still perform more complex logic inside each onMethod() with this structure. Just ensure you handle the cases appropriately.

Is there any performance gain with this approach?


Typically, there would not be noticeable performance differences, but cleaner code can often prevent logical errors.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу