检查模板函数的存在
问题描述:
如何检查这样的模板函数的存在:检查是否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()");
答
你以前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;
};
了解这个溶液一些注意事项:
- 指定当第e
read
成员函数T
(reader
),我们需要使用template
关键字来通知编译器名称reader
是一个模板。 - 使用
result_of
需要F(Args)
函数的语法,所以在这里我们得到的reader::read
类型为F
部分,然后通过reader
为Args
部分- 我们必须通过的
T
一个实例(reader)
到read
,因为它是一个成员函数(而不是static
或免费的),和成员函数隐式地采取他们正在呼吁类的实例的引用。
- 我们必须通过的
我编辑你的标签到C++ 14。 'std :: enable_if_t'在C++中不可用11 – AndyG