concept : yielding function pointer by using the plus trick

Hi, I have this code

1
2
3
4
5
6
7
8
9
/**
         *  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!



works fine with newer MSVC: https://godbolt.org/z/dqzsfo38n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#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);
}


compiles fine with VS2022 17.3.1 /std:c++latest

what does "yielding function pointer by using the plus trick" means??

in the concept, what does {+d }; mean?

@seeplus that small fragment also compiles in my machine!! But a larger program does not!!

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.
Last edited on
This does not compile!!!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
  *  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!
}




lam is callable!! should work!!

yes, that one ICEs MSVC. works on gcc and clang; https://godbolt.org/z/r1b99fPsG send a bug report

lam is callable!!
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).
Last edited on
Topic archived. No new replies allowed.