我希望能够内省一个C++类的名称,内容(即成员及其类型)等.我在这里说的是原生C++,而不是托管C++,它有反射.我意识到C++使用RTTI提供一些有限的信息.哪些额外的库(或其他技术)可以提供此信息?
我要求一个模板技巧来检测一个类是否具有给定签名的特定成员函数.
问题类似于这里引用的问题 http://www.gotw.ca/gotw/071.htm 但不一样:在Sutter的书中,他回答了C类必须提供成员函数的问题.一个特定的签名,否则程序将无法编译.在我的问题中,我需要做一些事情,如果一个类有这个功能,否则做"其他".
boost :: serialization面临类似的问题,但我不喜欢他们采用的解决方案:模板函数默认调用具有特定签名的自由函数(您必须定义),除非您定义特定的成员函数(在他们的情况下"序列化",它采用给定类型的2个参数)与特定签名,否则将发生编译错误.那就是实现侵入式和非侵入式序列化.
我不喜欢这个解决方案有两个原因:
我需要为没有该成员函数的类定义自定义行为,并且我的实体位于不同的名称空间内(我不想覆盖在一个名称空间中定义的全局函数,而我在另一个名称空间中)
你能给我一个解决这个难题的提示吗?
当涉及到"问题线"的"隐藏特征"时,没有C++的爱吗?想我会把它扔出去.C++的一些隐藏功能是什么?
我有这样的代码:
class RetInterface {...}
class Ret1: public RetInterface {...}
class AInterface
{
public:
virtual boost::shared_ptr<RetInterface> get_r() const = 0;
...
};
class A1: public AInterface
{
public:
boost::shared_ptr<Ret1> get_r() const {...}
...
};
Run Code Online (Sandbox Code Playgroud)
此代码无法编译.
在视觉工作室,它提出
C2555:覆盖虚函数返回类型不同且不协变
如果我不使用boost::shared_ptr但返回原始指针,代码编译(我理解这是由于C++中的协变返回类型).我可以看到这个问题是因为boost::shared_ptr的Ret1不是源自boost::shared_ptr的RetInterface.但我想返回boost::shared_ptr的Ret1在其他类使用,否则我必须在返回后投返回值.
为了创建算法模板函数,我需要知道类中的x或X(和y或Y)是模板参数.当我的函数用于MFC CPoint类或GDI + PointF类或其他类时,它可能很有用.他们都使用不同的x.我的解决方案可以简化为以下代码:
template<int> struct TT {typedef int type;};
template<class P> bool Check_x(P p, typename TT<sizeof(&P::x)>::type b = 0) { return true; }
template<class P> bool Check_x(P p, typename TT<sizeof(&P::X)>::type b = 0) { return false; }
struct P1 {int x; };
struct P2 {float X; };
// it also could be struct P3 {unknown_type X; };
int main()
{
P1 p1 = {1};
P2 p2 = {1};
Check_x(p1); // must return true
Check_x(p2); // must return false
return …Run Code Online (Sandbox Code Playgroud) 在http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx上,VC++团队正式声明他们尚未实现C++ 11核心功能"Expression SFINAE".但是,从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html复制的以下代码示例将被VC++编译器接受.
例1:
template <int I> struct A {};
char xxx(int);
char xxx(float);
template <class T> A<sizeof(xxx((T)0))> f(T){}
int main()
{
f(1);
}
Run Code Online (Sandbox Code Playgroud)
例2:
struct X {};
struct Y
{
Y(X){}
};
template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1
X f(Y, Y); // #2
X x1, x2;
X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2
Run Code Online (Sandbox Code Playgroud)
我的问题是:什么是"表达SFINAE"?
编辑,为了避免混淆:
decltype不不接受两个参数.看到答案.
以下两个结构可用于T在编译期间检查类型上成员函数的存在性:
// Non-templated helper struct:
struct _test_has_foo {
template<class T>
static auto test(T* p) -> decltype(p->foo(), std::true_type());
template<class>
static auto test(...) -> std::false_type;
};
// Templated actual struct:
template<class T>
struct has_foo : decltype(_test_has_foo::test<T>(0))
{};
Run Code Online (Sandbox Code Playgroud)
我认为这个想法是在检查成员函数的存在时使用SFINAE,因此如果p->foo()无效,则只test返回返回的省略号版本std::false_type.否则,第一个方法被定义T*并将返回std::true_type.实际的"切换"发生在第二个类中,它继承自返回的类型test.与不同的方法相比,这看起来更聪明,更"轻巧" is_same.
在decltype与两个参数第一次看令我感到诧异,因为我认为这只是得到一个表达式的类型.当我看到上面的代码时,我认为它类似于"尝试编译表达式并始终返回第二种类型.如果表达式无法编译则失败"(所以隐藏此专业化; SFINAE).
但:
然后我想我可以使用这个方法来编写任何"is valid expression"检查器,只要它依赖于某种类型T.例:
...
template<class T>
static auto test(T* p) -> decltype(bar(*p), std::true_type());
...
Run Code Online (Sandbox Code Playgroud)
这一点,所以我想,将返回 …
我正在努力升级一些C++代码以利用C++ 11中的新功能.我有一个特性类,其中有一些函数返回基本类型,这些函数大部分时间(但并不总是)返回一个常量表达式.我想根据功能是否做不同的事情constexpr.我提出了以下方法:
template<typename Trait>
struct test
{
template<int Value = Trait::f()>
static std::true_type do_call(int){ return std::true_type(); }
static std::false_type do_call(...){ return std::false_type(); }
static bool call(){ return do_call(0); }
};
struct trait
{
static int f(){ return 15; }
};
struct ctrait
{
static constexpr int f(){ return 20; }
};
int main()
{
std::cout << "regular: " << test<trait>::call() << std::endl;
std::cout << "constexpr: " << test<ctrait>::call() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
额外的int/ ...参数是这样的,如果两个函数在SFINAE之后可用,则第一个函数通过重载分辨率来选择. …
我正在尝试编写一个类型特征来检测一个类型是否重载了适合用于输出流的operator <<().
我错过了一些东西,因为我总是认为一个简单的空类没有操作符.
这里的代码:
template<typename S, typename T>
class is_streamable
{
template<typename SS, typename TT>
static auto test(SS&& s, TT&& t)
-> decltype(std::forward<SS>(s) << std::forward<TT>(t));
struct dummy_t {};
static dummy_t test(...);
using return_type = decltype(test(std::declval<S>(), std::declval<T>()));
public:
static const bool value = !std::is_same<return_type, dummy_t>::value;
};
class C {};
int main() {
std::cout << is_streamable<std::stringstream, C>::value << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
Run Code Online (Sandbox Code Playgroud)
这是在ideone:https://ideone.com/ikSBoT
我究竟做错了什么?
使用SFINAE,我可以检测给定的类是否具有某个成员函数.但是如果我想测试继承的成员函数呢?
以下在VC8和GCC4中不起作用(即检测到A具有成员函数foo(),但不会B继承成员函数):
#include <iostream>
template<typename T, typename Sig>
struct has_foo {
template <typename U, U> struct type_check;
template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1];
template <typename > static char (& chk(...))[2];
static bool const value = (sizeof(chk<T>(0)) == 1);
};
struct A {
void foo();
};
struct B : A {};
int main()
{
using namespace std;
cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true
cout << boolalpha …Run Code Online (Sandbox Code Playgroud) c++ ×10
sfinae ×7
templates ×7
c++11 ×5
constexpr ×1
covariance ×1
decltype ×1
g++ ×1
iostream ×1
reflection ×1
type-traits ×1
visual-c++ ×1