[cfe-dev] Compile error with libc++'s bind

Howard Hinnant hhinnant at apple.com
Fri May 20 14:37:42 PDT 2011


On May 20, 2011, at 3:30 PM, Howard Hinnant wrote:

> On May 20, 2011, at 3:18 PM, Howard Hinnant wrote:
> 
>> On May 20, 2011, at 2:59 PM, Jonathan Sauer wrote:
>> 
>>> Hello,
>>> 
>>> the following program fails to compile with clang trunk and libc++ trunk (note the implicit conversion from <const char*>
>>> to <std::string> when calling the functor in <doIt>):
>>> 
>>> #include <functional>
>>> 
>>> using namespace std::placeholders;
>>> 
>>> template <typename Functor>
>>> static void doIt(Functor f)
>>> {
>>> f("");
>>> }
>>> 
>>> static void method(const std::string&);	// A
>>> //static void method(const char*);	// B
>>> 
>>> int main(int, char**)
>>> {
>>> doIt(std::bind(&method, _1));
>>> }
>>> 
>>> 
>>> This results in the following error:
>>> 
>>> $ ~/LLVM/build/Release+Asserts/bin/clang -std=c++0x -stdlib=libc++ clang.cpp
>>> In file included from clang.cpp:1:
>>> /usr/include/c++/v1/functional:1620:8: error: no type named 'type' in 'std::__1::__invoke_of<void
>>>    (*&)(const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>
>>>> &), char const (&)[1]>'
>>>> ::type type;
>>> 
>>> 
>>> Commenting line (A) and uncommenting line (B), i.e. removing the implicit conversion, makes the code compile.
>>> 
>>> I looked into the standard, section 20.8, but was unable to find anything about implicit conversions, although it seems to
>>> me from reading 20.8.2p1 that they should be allowed.
>>> 
>>> A similar code used to compile with an older version of libc++ (most likely before Howard's implementations in r131639ff.
>>> 
>>> So my question is: Is this a bug in libc++, or are implicit conversions not allowed, and the similar code used to compile
>>> because of an implementation artefact that was removed during r131639ff?
>> 
>> This looks like a bug either in the new __invoke_of trait, or in clang's SFINAE / overload handling. Not sure yet.  Investigating...
> 
> At the very least we have a misleading error message:
> 
> error: no type named 'type' in 'std::__1::__invoke_of<void (*&)(const std::__1::basic_string<char,
>      std::__1::char_traits<char>, std::__1::allocator<char> > &), char const (&)[1]>'
>> ::type type;
>    ~~~^~~~
> 
> And yet:
> 
> #include <type_traits>
> #include <string>
> 
> static void method(const std::string&) {}	// A
> 
> #include <iostream>
> 
> int main()
> {
>    std::cout << std::__invokable<void (*&)(const std::string&), char const (&)[1]>::value << '\n';
>    std::cout << typeid(std::__invoke_of<void (*&)(const std::string&), char const (&)[1]>::type).name() << '\n';
> }
> 
> outputs:
> 
> 1
> v
> 
> Meaning std::__invoke_of<void (*&)(const std::string &), char const (&)[1]> >::type exists and has type void.

I've submitted this bugzilla:

http://llvm.org/bugs/show_bug.cgi?id=9975

Howard




More information about the cfe-dev mailing list