如何检测功能是否存在?

pin*_*gul 6 c++ templates metaprogramming template-meta-programming c++11

我正在尝试检测函数的特定重载是否可调用。我以为我可以做一些类似于此答案的事情,但是我相信问题在于函数签名template<typename From, typename To> convert(const From&)定义得很好,但是实例化却没有。

#include <iostream>
#include <string>

template<typename From, typename To>
To convert(const From& from)
{
    // I have a lot of additional template specializations for this function
    return from; 
}

template<typename From, typename To>
struct IsConvertible
{
    template<typename = decltype(convert<From, To>(From()))>
    static std::true_type test(int);
    template<typename T>
    static std::false_type test(...);

    static bool const value = decltype(test(0))::value;
};

int main()
{
    std::cout << "IsConvertible=" << IsConvertible<int, float>::value << std::endl;
    // Returns 1 as expected

    std::cout << "IsConvertible=" << IsConvertible<int, std::string>::value << std::endl;
    // Returns 1, expected 0. The issue seems to be that decltype(convert<From, To>(From()))
    // is somehow ok, although convert<int, std::string>(1) definitly isn't
}

Run Code Online (Sandbox Code Playgroud)

我想IsConvertible用于其他一些元编程。是否可以检测该template<typename From, typename To> To convert(const From&)函数是否实际可调用?

Jar*_*d42 2

附有声明

template<typename From, typename To> To convert(const From& from);
Run Code Online (Sandbox Code Playgroud)

你的特质

template<typename From, typename To>
struct IsConvertible
Run Code Online (Sandbox Code Playgroud)

总是会检测到convert功能的存在。

解决这个问题的一种方法是重载和/或 SFINAE:

template <typename> struct Tag{};

int convertImpl(tag<int>, const std::string& from);
float convertImpl(tag<float>, const std::string& from);
// overloads ...

template<typename From, typename To>
auto convert(const From& from)
-> decltype(convertImpl(tag<To>{}, from))
{
    return convertImpl(tag<To>{}, from);
}
Run Code Online (Sandbox Code Playgroud)