3

I'm trying to customize std::function and beginning with the following code:

#include <functional>

template <typename>
struct my_function;

template <typename R, typename... Args>
struct my_function<R(Args...)> : std::function<R(Args...)> {
  using base = std::function<R(Args...)>;

  using base::function;
}; 

int main() {
  my_function<int(int)> f = nullptr;
}

I'm expecting that the constructor from std::function that takes an std::nullptr_t object is inherited by my_function. So, the code should compile fine. While GCC 5.2 (C++14) has no problem in compiling the code, clang 3.6 (C++14) produced the following error message which is quite confusing:

n file included from main.cpp:1:
/usr/include/c++/v1/functional:1454:41: error: no type named 'type' in 'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration
                                        __callable<_Fp>::value &&
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:15: note: in instantiation of member function 'std::__1::function<int (int)>::function' requested here
  using base::function;
              ^
main.cpp:14:25: note: while substituting deduced template arguments into function template 'my_function' [with _Fp = nullptr_t]
  my_function<int(int)> f = nullptr;
                        ^
1 error generated.

Is this a clang bug or my code is just incorrect? If (very fortunately) the latter is true, how should I fix the code?

Lingxi
  • 14,579
  • 2
  • 37
  • 93
  • Your program builds clean for me with ubuntu's builds of clang version 3.6.2 and clang version clang version 3.7.0 – Mike Kinghan Jan 24 '16 at 08:13
  • @MikeKinghan I'm using clang on Mac OS X actually. – Lingxi Jan 24 '16 at 08:20
  • I wonder what patch version you have? – Mike Kinghan Jan 24 '16 at 08:24
  • 3
    This is one of the issues fixed by [P0136](http://wg21.link/p0136), caused by the way inheriting constructors were specified in the standard. – T.C. Jan 24 '16 at 08:35
  • 1
    @MikeKinghan It depends on the standard library you use. The constructor at issue must be constrained; libstdc++ and libc++ constrain it using different SFINAE methods, one of which (libc++'s) interacts poorly with pre-P0136 inheriting constructors. – T.C. Jan 24 '16 at 08:42
  • @T.C. So, it's a C++14 bug? Guess I will have to manually reproducing the constructors then for portability. – Lingxi Jan 24 '16 at 08:58
  • 1
    Just noting: You can also say `using my_function::function::function;` here, you don't need the typedef in order to avoid repeating the baseclass name. – Johannes Schaub - litb Jan 26 '16 at 18:00
  • @JohannesSchaub-litb In fact, in my actual code, the class is named `function` instead of `my_function`. – Lingxi Jan 27 '16 at 02:42
  • @JohannesSchaub-litb I've never seen that syntax before, and it provided me with a concise, Clang-friendly way to inherit constructors in a class template hierarchy, so thanks for that! What language feature is it that allows us to refer to base constructors like that? – Ose Jul 08 '16 at 14:54
  • 1
    @ose injected class names – Johannes Schaub - litb Jul 08 '16 at 16:21

0 Answers0