[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