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

Howard Hinnant hhinnant at apple.com
Fri May 20 12:30:19 PDT 2011


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.

Howard




More information about the cfe-dev mailing list