I have a problem with a C ++ meta function that I don't understand. I am building an assembly of Apple clang 8.1.0 using C ++ 14. The following is the working code illustrating the problem.
I rolled up the metafound from another place and I'm trying to use it. It is designed to detect functions called "bananify" that have a type parameter passed to the metafile. You name it ...
BananifyDetector<int>::value
should return true if it can see the declared form function ...
bananify(int)
The problem is that it only works if the desired function is declared before defining the BananifyFinder template, as opposed to creating it. So in my code example, I would expect both
BananifyFinder<int>
BananifyFinder<std::string>
to succeed with the code I have below, but due to where bananify (std :: string) was defined, it fails.
This is disappointing, as if I were placing the detector functions in the header files, I should include the order known in the client code, which is a serious pain and it may not be possible to get the right in some circumstances.
I'm not sure what is going on here. Is it a C ++ function, a bug in clang, or something dumb that I did?
Any help was appreciated.
#include <iostream>
#include <type_traits>
double bananify(int)
{
return 0.0;
}
template<class ARG1>
class BananifyFinder {
private :
template<typename ...> using VoidT_ = void;
template<typename A1, typename = void>
struct Test_ : std::false_type
{
typedef void returnType;
};
template<typename A1>
struct Test_<A1, VoidT_<decltype(bananify(std::declval<A1>()))>> : std::true_type
{
typedef decltype(bananify(std::declval<A1>())) returnType;
};
public :
typedef typename Test_<ARG1>::returnType returnType;
constexpr static bool value = Test_<ARG1>::value;
};
std::string bananify(std::string)
{
return "s";
}
class Nothing{};
template<class T>
void CheckBanana(const std::string &str)
{
using DetectedType = BananifyFinder<T>;
std::cout << str << " detected is " << DetectedType::value << std::endl;
std::cout << str << " returns is " << typeid(typename DetectedType::returnType).name() << std::endl << std::endl;
}
int main(int argc, char *argv[])
{
CheckBanana<int>("BananifyFinder<int> ");
CheckBanana<std::string>("BananifyFinder<std::string> ");
CheckBanana<Nothing>("BananifyFinder<Nothing> ");
}