/**
* Constraints a deleter to be or to yield a function pointer.
*/
template<typename D>
concept yields_fp = requires(D d) {
// yielding function pointer by using the plus trick
{+d};
requires std::is_function_v<std::remove_pointer_t<decltype(+d)>>;
};
which does not compile (gives internal compiler error) in Visual Studio 2022 version 17.3.1 using /std:c++20 or /std:c++latest
what does this trick do and how can I rewrite it so it compiles?
this is definitely a problem with the concept definition!
#include <type_traits>
/**
* Constraints a deleter to be or to yield a function pointer.
*/
template<typename D>
concept yields_fp = requires(D d) {
// yielding function pointer by using the plus trick
{+d };
requires std::is_function_v<std::remove_pointer_t<decltype(+d)>>;
};
void f(void) {}
auto demo(yields_fp auto arg) {
arg();
}
int main() {
demo(f);
}
what does "yielding function pointer by using the plus trick" means??
I would call it an 'idiom' rather than a 'trick' - it's something unary+ is used for; explicitly triggering lvalue conversions (and integer promotions, but I suspect this usage is more common).
what does {+d }; mean?
it says "concept is satisfied if the expression +d compiles." Call "demo" with an std::string argument instead of a function in the example above, and that is where it will report an error.
/**
* Constraints a deleter to be or to yield a function pointer.
*/
template<typename D>
concept yields_fp = requires(D d) {
// yielding function pointer by using the plus trick
{+d};
requires std::is_function_v<std::remove_pointer_t<decltype(+d)>>;
};
void ff(void) {}
auto demo(yields_fp auto arg) {
arg();
}
auto lam = []()
{
};
void useConceptYields_fp() {
demo(ff);
demo(lam); // INTERNAL COMPILER ERROR!
}
the concept isn't checking if it's callable. It's checking if the unary plus expression applied to it compiles and has a function type (weird, but I can write such op+) or a function pointer type (common for functions and indeed captureless lambdas).