检查模板函数的存在

问题描述:

如何检查这样的模板函数的存在:检查是否reader结构有read算术值检查模板函数的存在

struct reader { 
    template<typename T> 
    std::enable_if_t<std::is_arithmetic<T>::value, T> read() { 
     return {}; 
    } 
}; 

我用一个检查这样的:

template <typename T> 
struct test_read { 
    static constexpr auto value = std::is_convertible<decltype(std::declval<T>().read<int>()),int>::value;  
}; 

但是编译器会抱怨:

error: wrong number of template arguments (1, should be 2) 
static constexpr auto value = std::is_convertible<decltype(std::declval<T>().read<int>()),int>::value; 

请给我哟你对此的建议。

谢谢。


更新:这里是最后的版本我讨论后得到的,我希望大家会发现它的代码

struct not_reader { 

}; 


struct reader { 
    template<typename T> 
    std::enable_if_t<std::is_arithmetic<T>::value, T> read() { 
     return {}; 
    } 
}; 


template<class T, class Elem> 
struct has_read { 
private: 
    template<class C, typename=void> 
    struct test_read : std::false_type { 
    }; 
    template<class C> 
    struct test_read<C, typename std::enable_if<std::is_convertible<decltype(std::declval<C>().template read<Elem>()), Elem>::value>::type> 
      : std::true_type { 
    }; 
public: 
    using type = typename test_read<T>::type; 
    static constexpr bool value = test_read<T>::value; 
}; 


static_assert(has_read<reader, int>::value, "reader should have int read()"); 
static_assert(!has_read<not_reader, int>::value, "not_reader should not have int read()"); 
+0

我编辑你的标签到C++ 14。 'std :: enable_if_t'在C++中不可用11 – AndyG

你以前read()

static constexpr auto value 
    = std::is_convertible< 
     decltype(std::declval<T>().template read<int>()),int>::value; 
// .................................#########  

但我忘了template有帮助不要认为你的代码可以检查“如果reader结构有read算术值”:尝试调用test_read与类型int,你应该得到一个编译错误。

下面是一个替代的解决方案

#include <type_traits> 

struct reader 
{ 
    template<typename T> 
    std::enable_if_t<std::is_arithmetic<T>::value, T> read() 
    { return {}; } 
}; 

template <typename, typename = void> 
struct readTypeRet 
{ using type = void; }; 

template <typename T> 
struct readTypeRet<T, decltype(std::declval<T>().template read<int>(), void())> 
{ using type = decltype(std::declval<T>().template read<int>()); }; 

template <typename T> 
struct test_read 
    : public std::is_convertible<typename readTypeRet<T>::type, int> 
{ }; 

int main() 
{ 
    static_assert(test_read<reader>::value == true, "!"); 
    static_assert(test_read<int>::value == false, "!"); 
} 
+0

它工作正常,我忘记了模板函数的模板关键字,比如'read'。这很容易理解:)谢谢! – haint504

要简要重申你的问题的是一个有点清晰方面的例子:

  • 你有一些函数将返回T如果T满足is_arithmetic,否则返回void
  • 你想断言调用这个函数int wi会一个类型,可转换返回int

我认为的最短路径来解决你的代码是利用std::result_of(C++ 11/14,在C++ 17使用std::invoke_result_t):

template<class T> 
struct test_read { 
static constexpr auto value = std::is_convertible< 
    typename std::result_of<decltype(&T::template read<int>)(T)>::type, int 
    >::value;  
}; 

Live Demo

了解这个溶液一些注意事项:

  • 指定当第e read成员函数Treader),我们需要使用template关键字来通知编译器名称reader是一个模板。
  • 使用result_of需要F(Args)函数的语法,所以在这里我们得到的reader::read类型为F部分,然后通过readerArgs部分
    • 我们必须通过的T一个实例( reader)read,因为它是一个成员函数(而不是static或免费的),和成员函数隐式地采取他们正在呼吁类的实例的引用。
+0

谢谢,这个更简洁,但是'T'应该代替'reader',对吧? – haint504

+0

@ haint504哎呀,是的 – AndyG