Dec 19, 2022

[C++] non-deduced context usage in template function parameter deduction.

Interesting question raised in stackoverflow about non-deduced context usage for deduced type for function.

Explained inline:

#include <iostream>
#include <functional>
#include <type_traits>
using namespace std;

/**
 * foo shall fail due to TArgs's first 2 specialized argument are;
 * in our example below in main, (int, int);
 * however, the deduce of packing continues from the argument in case needs to be extended;
 * thus TArgs is deduced to empty pack(because [](int,int){} has both int args matched),
 * and std::function<void(empty)> can not take [](int,int){};
 */
template <typename... TArgs>
void foo(std::function<void(TArgs...)> f) {
}

/**
 * Non-deduced contexts compes into the play.
 * https://vsdmars.blogspot.com/2022/07/c20-stdtypeidentity-for-non-deduced.html
 * Type inside std::type_identity_t<...> is replaced not deduced.
 */ 
template <typename... TArgs>
void foo_cure(std::type_identity_t<std::function<void(TArgs...)>> f) {
}

int main() { 
    // foo<int,int>([](int, int){}); // no can do.
    foo_cure<int,int>([](int, int){});
}

code in action:
https://godbolt.org/z/qrG5G53ar

There are other ways around for OP's question, e.g. using class template with static member function
taking the specialized class template arguments for the static member function; or, simply,
use universal reference template for the standalone template function taking the lambda expression object with variable argument-types.

Alas, while start coding in Rust, C++ makes me feel taking more time ruminating for the better solution than solving the problem, kinda like Perl?! In the long run I bet Rust shall take over; however, template programming is fun. 😄

Further read:
[C++20] std::type_identity for Non-deduced contexts

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.