Telegram 源码解读点滴记录

1.test_callable_plain,作用:判断参数是否与函数声明一致

using false_t = char;
struct true_t {
	false_t data[2];
};
static_assert(sizeof(false_t) != sizeof(true_t), "I can't work :(");
//----------------------------is_callable_plain_v-------------------------------------
template <
	typename Method,
	typename ...Args,
	typename = decltype(std::declval<Method>()(
		std::declval<Args>()...))>
true_t test_callable_plain(Method &&, Args &&...) noexcept;
false_t test_callable_plain(...) noexcept;

template <typename Method, typename ...Args>
struct is_callable_plain
	: std::bool_constant<(
		sizeof(test_callable_plain(
			std::declval<Method>(),
			std::declval<Args>()...
		)) == sizeof(true_t))> {
};

template <typename Method, typename ...Args>
constexpr bool is_callable_plain_v = is_callable_plain<Method, Args...>::value;

//--------------------------------is_callable_tuple_v--------------------------------------
template <typename Arg>
const Arg& const_ref_val()  noexcept ;

template <
	typename Method,
	typename ...Types,
	typename = decltype(std::declval<Method>()(
		std::declval<Types>()...))>
true_t test_callable_tuple(
	Method&&,
	std::tuple<Types...>&&) noexcept;

template <
	typename Method,
	typename ...Types,
	typename = decltype(std::declval<Method>()(
		const_ref_val<Types>()...))>
true_t test_callable_tuple(
	Method&&,
	const std::tuple<Types...>&) noexcept;

false_t test_callable_tuple(...) noexcept;

template <typename Method, typename Arg>
constexpr bool is_callable_tuple_v = (sizeof(test_callable_tuple(
	std::declval<Method>(),
	std::declval<Arg>())) == sizeof(true_t));

//----------------------------------------综合两都判断---------------------------
template <typename Method, typename ...Args>
struct is_callable;

template <typename Method>
struct is_callable<Method>
	: std::bool_constant<
		is_callable_plain_v<Method>> {
};

template <typename Method, typename Arg>
struct is_callable<Method, Arg>
	: std::bool_constant<
		is_callable_plain_v<Method, Arg> ||
		is_callable_tuple_v<Method, Arg> ||
		is_callable_plain_v<Method>> {
};

template <typename Method, typename ...Args>
constexpr bool is_callable_v = is_callable<Method, Args...>::value;

template <typename Method, typename Arg>
inline decltype(auto) callable_invoke(Method &&method, Arg &&arg) {
	if constexpr (is_callable_plain_v<Method, Arg>) {
		return std::forward<Method>(method)(std::forward<Arg>(arg));
	} else if constexpr (is_callable_tuple_v<Method, Arg>) {
		return std::apply(
			std::forward<Method>(method),
			std::forward<Arg>(arg));
	} else if constexpr (is_callable_v<Method>) {
		return std::forward<Method>(method)();
	} else {
		static_assert(false_(method, arg), "Bad callable_invoke() call.");
	}
}

//使用示例代码
void FnC(int age, string name) {

}

void FnTuple(int a,int b) {

}

int main()
{
    auto c1 = test_callable_plain(FnC, 1);        //c1值为false_t
    auto c2 = test_callable_plain(FnC, 1,"FFF");    //c2值为true_t
    constexpr auto c3 = is_callable_plain_v<decltype(FnC), int>; //false
    constexpr auto c4 = is_callable_plain_v<decltype(FnC), int,string>;//true
    
    
    const std::tuple<int,int> t1 = std::make_tuple(1, 1);
    auto f = test_callable_tuple(FnTuple,t1);                        //true_t

	const std::tuple<int, string> t2 = std::make_tuple(1, "FF");
	auto f2 = test_callable_tuple(FnTuple, t2);                    //false_t
}

 

posted @ 2023-04-26 08:59  情三  阅读(64)  评论(0编辑  收藏  举报