是否有可能编写一个模板,根据某个成员函数是否定义在类上而改变行为?
下面是我想写的一个简单的例子:
template<class T>
std::string optionalToString(T* obj)
{
if (FUNCTION_EXISTS(T->toString))
return obj->toString();
else
return "toString not defined";
}
因此,如果类T定义了toString(),那么它就使用它;否则,它就不会。我不知道如何做的神奇部分是“FUNCTION_EXISTS”部分。
如果方法恰好定义在基类中,那么这里由litb提供的标准c++解决方案将不能像预期的那样工作。
处理这种情况的解决方案请参考:
俄语:
http://www.rsdn.ru/forum/message/2759773.1.aspx
由罗马人翻译的英文。Perepelitsa:
http://groups.google.com/group/comp.lang.c++.moderated/tree/browse_frm/thread/4f7c7a96f9afbe44/c95a7b4c645e449f?pli=1
它非常聪明。然而,这种解决方案的一个问题是,如果被测试的类型不能用作基类(例如基本类型),则会给出编译器错误。
在Visual Studio中,我注意到如果使用没有参数的方法,则需要在参数周围插入一对额外的冗余()来在sizeof表达式中推导()。
我一直在寻找一个方法,允许以某种方式不绑定结构名has_member类的成员的名字。
实际上,如果lambda可以被允许在未求值的表达式中(这是被标准禁止的),这将更简单,即has_member<ClassName, SOME_MACRO_WITH_DECLTYPE(member_name)>
#include <iostream>
#include <list>
#include <type_traits>
#define LAMBDA_FOR_MEMBER_NAME(NAME) [](auto object_instance) -> decltype(&(decltype(object_instance)::NAME)) {}
template<typename T>
struct TypeGetter
{
constexpr TypeGetter() = default;
constexpr TypeGetter(T) {}
using type = T;
constexpr auto getValue()
{
return std::declval<type>();
}
};
template<typename T, typename LambdaExpressionT>
struct has_member {
using lambda_prototype = LambdaExpressionT;
//SFINAE
template<class ValueT, class = void>
struct is_void_t_deducable : std::false_type {};
template<class ValueT>
struct is_void_t_deducable<ValueT,
std::void_t<decltype(std::declval<lambda_prototype>()(std::declval<ValueT>()))>> : std::true_type {};
static constexpr bool value = is_void_t_deducable<T>::value;
};
struct SimpleClass
{
int field;
void method() {}
};
int main(void)
{
const auto helpful_lambda = LAMBDA_FOR_MEMBER_NAME(field);
using member_field = decltype(helpful_lambda);
std::cout << has_member<SimpleClass, member_field>::value;
const auto lambda = LAMBDA_FOR_MEMBER_NAME(method);
using member_method = decltype(lambda);
std::cout << has_member<SimpleClass, member_method>::value;
}