From 53cae289b7d71688a13f6aa902e79342f5e32623 Mon Sep 17 00:00:00 2001 From: Mike Crowe Date: Thu, 28 Dec 2017 19:45:08 +0000 Subject: [PATCH] core: Report useful error message if function pointer is passed The value constructor generates a useful error message if the client code passes a pointer to something that isn't void. Unfortunately, the compiler doesn't get that far if a function pointer is passed because the value(T *p) forwarding constructor ends up trying to call itself which results in an error like: .../fmt/core.h:485:34: error: constructor delegates to itself value(T *p) : value(as_const(p)) {} So, let's add an extra constructor that is a better match for function pointers so that a similar useful error message can be emitted. We need to force the compiler to decide whether to generate the message only when something would actually cause the constructor to be called by making the static_assert expression use the template parameter. --- include/fmt/core.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/fmt/core.h b/include/fmt/core.h index ed4bc45a..6c10b508 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -468,6 +468,18 @@ class value { set(pointer, p); } + // Match function pointers explicitly. If we do not then the + // forwarding T * constructor below will end up trying to call + // itself when a function pointer is passed, which leads to a + // confusing error message. + template + value(T (*p)(Args...)) { + // This static_assert must use something that is dependent on T, + // otherwise it will always fire, so let's use the same check as + // above - it will never match. + static_assert(std::is_same::value, "formatting of function pointers is disallowed"); + } + template value(T *p) : value(as_const(p)) {}