From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22432 invoked by alias); 17 Dec 2012 18:20:53 -0000 Received: (qmail 22353 invoked by uid 48); 17 Dec 2012 18:20:29 -0000 From: "redi at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/55722] New: failed static_assert won't trigger a second time Date: Mon, 17 Dec 2012 18:20:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Keywords: diagnostic X-Bugzilla-Severity: normal X-Bugzilla-Who: redi at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2012-12/txt/msg01684.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D55722 Bug #: 55722 Summary: failed static_assert won't trigger a second time Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned@gcc.gnu.org ReportedBy: redi@gcc.gnu.org Created attachment 28986 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=3D28986 reduced testcase #include #include template struct _Bind_simple; template struct _Bind_simple<_Callable(_Args...)> { template explicit _Bind_simple(_Callable2&& __callable, _Args2&&... __args) { } }; template struct _Bind_simple_helper { typedef typename std::decay<_Func>::type __func_type; typedef _Bind_simple<__func_type(typename std::decay<_BoundArgs>::type.= ..)> type; typedef std::result_of<__func_type(typename std::decay<_BoundArgs>::type...)> __result_of; }; template struct __assert_callable { static_assert(_Callable::value, "Invalid arguments for callable type"); }; template __assert_callable __check_callable(...); template, typename =3D typename _Tp::__result_of::type> typename _Tp::type __check_callable(int); template decltype(__check_callable<_Callable, _Args...>(0)) __bind_simple(_Callable&& __callable, _Args&&... __args) { typedef _Bind_simple_helper<_Callable, _Args...> __helper_type; typedef typename __helper_type::type __bindexpr_type; return __bindexpr_type( std::forward<_Callable>(__callable), std::forward<_Args>(__args)...); } template void call(_Callable&& __f, _Args&&... __args) { auto __bound_functor =3D __bind_simple(std::forward<_Callable>(__f), std::forward<_Args>(__args)...); } void f(int&); void test01() { call(f); #ifndef ONLY_ONE call(f, 1, 2); #endif } When compiled with ONLY_ONE defined this produces a nice "static assertion failed" message, as intended. $ g++ -std=3Dc++11 -DONLY_ONE sa.cc: In instantiation of =E2=80=98struct __assert_callable >=E2=80=99: sa.cc:42:51: required by substitution of =E2=80=98template decltype (__check_callable<_Callable, _Args ...>(0)) __bind_simple(_Callable&&, _Args&& ...) [with _Callable =3D void (&)(int&);= _Args =3D {}]=E2=80=99 sa.cc:55:39: required from =E2=80=98void call(_Callable&&, _Args&& ...) [= with _Callable =3D void (&)(int&); _Args =3D {}]=E2=80=99 sa.cc:62:9: required from here sa.cc:28:5: error: static assertion failed: Invalid arguments for callable = type static_assert(_Callable::value, "Invalid arguments for callable type"); ^ But if ONLY_ONE is not defined, so there's a second invalid call(), the nice clear diagnostic turns into an unpleasant mess: $ g++ -std=3Dc++11 sa.cc: In instantiation of =E2=80=98struct __assert_callable >=E2=80=99: sa.cc:42:51: required by substitution of =E2=80=98template decltype (__check_callable<_Callable, _Args ...>(0)) __bind_simple(_Callable&&, _Args&& ...) [with _Callable =3D void (&)(int&);= _Args =3D {}]=E2=80=99 sa.cc:55:39: required from =E2=80=98void call(_Callable&&, _Args&& ...) [= with _Callable =3D void (&)(int&); _Args =3D {}]=E2=80=99 sa.cc:62:9: required from here sa.cc:28:5: error: static assertion failed: Invalid arguments for callable = type static_assert(_Callable::value, "Invalid arguments for callable type"); ^ sa.cc: In instantiation of =E2=80=98decltype (__check_callable<_Callable, _= Args ...>(0)) __bind_simple(_Callable&&, _Args&& ...) [with _Callable =3D void (&)(int&); _Args =3D {int, int}; decltype (__check_callable<_Callable, _Args ...>(0)) =3D __assert_callable >]=E2=80= =99: sa.cc:55:39: required from =E2=80=98void call(_Callable&&, _Args&& ...) [= with _Callable =3D void (&)(int&); _Args =3D {int, int}]=E2=80=99 sa.cc:64:15: required from here sa.cc:47:96: error: could not convert =E2=80=98_Bind_simple((* & std::forward((* & __callable))), (* & std::forward((* & __args#0))), (* & std::forward((* & __args#1)))= )=E2=80=99 from =E2=80=98__bindexpr_type {aka _Bind_simple}= =E2=80=99 to =E2=80=98__assert_callable >=E2=80=99 return __bindexpr_type( std::forward<_Callable>(__callable), std::forward<_Args>(__args)...); =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20 ^ sa.cc: In instantiation of =E2=80=98_Bind_simple<_Callable(_Args ...)>::_Bind_simple(_Callable2&&, _Args2&& ...) [with _Callable2 =3D void (&)(int&); _Args2 =3D {int, int}; _Callable =3D void (*)(int&); _Args =3D {= int, int}]=E2=80=99: sa.cc:47:96: required from =E2=80=98decltype (__check_callable<_Callable,= _Args ...>(0)) __bind_simple(_Callable&&, _Args&& ...) [with _Callable =3D void (&)(int&); _Args =3D {int, int}; decltype (__check_callable<_Callable, _Args ...>(0)) =3D __assert_callable >]=E2=80= =99 sa.cc:55:39: required from =E2=80=98void call(_Callable&&, _Args&& ...) [= with _Callable =3D void (&)(int&); _Args =3D {int, int}]=E2=80=99 sa.cc:64:15: required from here sa.cc:12:7: warning: unused parameter =E2=80=98__callable=E2=80=99 [-Wunuse= d-parameter] _Bind_simple(_Callable2&& __callable, _Args2&&... __args) ^ sa.cc:12:7: warning: unused parameter =E2=80=98__args#0=E2=80=99 [-Wunused-= parameter] sa.cc:12:7: warning: unused parameter =E2=80=98__args#1=E2=80=99 [-Wunused-= parameter] sa.cc: In function =E2=80=98decltype (__check_callable<_Callable, _Args ...= >(0)) __bind_simple(_Callable&&, _Args&& ...) [with _Callable =3D void (&)(int&);= _Args =3D {int, int}; decltype (__check_callable<_Callable, _Args ...>(0)) =3D __assert_callable >]=E2=80=99: sa.cc:48:3: warning: control reaches end of non-void function [-Wreturn-typ= e] } ^ Why doesn't the static_assertion happen for the second call? I'm trying to use this static assertion to simplify diagnostics for invalid std::thread initializations or std::call_once uses, but it only helps for t= he first such error.