我想写一个类型特征来检查某个类型是否有成员member.如果member是公开的,有很多方法可以做到这一点(例如void_t),其中最简洁的可能是Yakkcan_apply(最终可以调用std::is_detected):
struct C {
int member;
};
template <typename T>
using member_type = decltype(&T::member);
template <typename T>
using has_member = can_apply<member_type, T>;
static_assert(has_member<C>{}, "!"); // OK
Run Code Online (Sandbox Code Playgroud)
但如果该成员是私人的,那么这种特性就会失败,因为访问权限member是不正常的(我们不是朋友),并且由于访问原因而形成不良与由于这种事情导致的不良形式之间没有区别.存在的原因:
class D {
int member;
};
static_assert(has_member<D>{}, "!"); // error
Run Code Online (Sandbox Code Playgroud)
有没有办法在所有访问控制中编写这样的成员检查程序?
这是我正在尝试做的事情:
template <typename T> struct Model
{
vector<T> vertices ;
#if T has a .normal member
void transform( Matrix m )
{
each vertex in vertices
{
vertex.pos = m * vertex.pos ;
vertex.normal = m * vertex.normal ;
}
}
#endif
#if T has NO .normal member
void transform( Matrix m )
{
each vertex in vertices
{
vertex.pos = m * vertex.pos ;
}
}
#endif
} ;
Run Code Online (Sandbox Code Playgroud)
我已经看过使用的例子enable_if,但是我无法理解如何应用enable_if这个问题,或者甚至可以应用它.
我正在寻找一种方法来检测模板类是否具有方法begin,end和resize.
我尝试了这个答案的修改版本:
#include <iostream>
#include <vector>
// SFINAE test
template <typename T>
class has_method
{
typedef char one;
struct two { char x[2]; };
template <typename C> static one test( decltype(&C::begin) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
int main(int argc, char *argv[])
{
std::cout << has_method<std::vector<int>>::value << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然而,这会打印 0。有趣的是,这将适用于cbeginandcend但不适用于begin, end …
在我的代码中的某些情况,我最终只在定义了该函数时调用该函数,否则我不应该.我怎样才能实现这一目标?
like:
if (function 'sum' exists ) then invoke sum ()
Run Code Online (Sandbox Code Playgroud)
可能是另一种方式来问这个问题是:如何确定函数是否在运行时定义,如果是,则调用.
由于一些奇怪的原因,g ++(版本4.5.0和4.5.2)无法编译此代码:
bool somefunc() {
return false;
}
class C {
public:
static const int a = 0;
static const int b = 1;
};
class myclass {
public:
int check() {
return somefunc() ? C::a : C::b;
// if(somefunc()) return C::a; else return C::b;
}
};
int main() {
myclass obj;
obj.check();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它给了我这个错误:
/tmp/ccyvvTUy.o:/home/mati/test.cpp:14: undefined reference to `C::a'
/tmp/ccyvvTUy.o:/home/mati/test.cpp:14: undefined reference to `C::b'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
如果我将有问题的行更改为注释行,它编译得很好,这很奇怪.我的代码是否有问题以及我对C++不了解的东西或它只是G ++中的一个错误?
我知道基本的规则,使用inline,enum而const不是#define,这不是我追求这个问题.我想知道的是#define在C++中使用宏以及如何使用宏的可接受场景.
请不要发布问题或链接到"define vs const"问题或"预处理器与编译器",我已经通过了Scott Meyers的Effective C++,我知道一个优于另一个的优点.
然而,经过几个小时的网上冲浪,我觉得#define被认为是C++中的某种弱者,但我确信必须有一个案例,使用它可以接受甚至是可取的.
为了推动这个问题,我猜想我可以想到的一个场景是创建一个DEBUG基于它的宏,它可以打印所有代码以及用于调试目的的所有内容.
#include <iostream>
void foo()
{
std::cout << "global foo()" << std::endl;
}
struct A {
void foo()
{
std::cout << "A::foo()" << std::endl;
}
};
struct B : public A {
void call()
{
foo();
}
};
int main(int argc, char **argv )
{
B b;
b.call();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这给出了预期的结果:
A::foo()
Run Code Online (Sandbox Code Playgroud)
但是在更改了两行之后(B类到模板):
#include <iostream>
void foo()
{
std::cout << "global foo()" << std::endl;
}
struct A {
void foo()
{
std::cout << "A::foo()" << std::endl;
}
}; …Run Code Online (Sandbox Code Playgroud) 我现在想要制作模板,将一些元素推送到支持push_back运算符的向量和其他类型.
我可以这样做
template<typename T>
T fill(size_t n) {
T v;
//(1)
for(size_t i = 0; i < n; ++i){
v.push_back(generate_some_how());
}
return v;
}
Run Code Online (Sandbox Code Playgroud)
有用.但现在我想提高支持它的类型的速度v.reserve(n);而不是(1).但我仍然希望能够为无法编译的类型编译此代码reserve
这是一种简单的方法吗?
我知道我可能专门研究硬编码类型但它看起来并不好.
C++ 11没问题.
我认为"适当"的实现is_swappable如下:
template<class T, class U = T> struct is_swappable<T, U> : /* see below */ { }
Run Code Online (Sandbox Code Playgroud)
is_swappable从std::true_typeT和U 继承Swappable,否则从std::false_type.
我尝试了很多东西,但SFINAE似乎没有用.这是一个特别讨厌的反例:
struct A {
A() {}
~A() {}
A(const A&) = delete;
A(A&&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
显然A不是Swappable.然而,我能提出的任何通用解决方案都无法正确处理上述示例.
我试过的SFINAE实现,但没有工作看起来像这样:
namespace with_std_swap {
using std::swap;
template<class T, class U, class =
decltype(swap(std::declval<T&>(), std::declval<U&>()))>
std::true_type swappable_test(int);
template<class, class> std::false_type swappable_test(...);
}
template<class T, class U = T>
struct is_swappable
: decltype(with_std_swap::using_std_swap::swappable_test<T, …Run Code Online (Sandbox Code Playgroud) 我需要一个简单的方法来获取类的对象的数量/长度/大小T这里T是某种集合类型,如中std::map,std::list,std::vector,CStringArray,CString,std::string,...
对于大多数标准类型,T::size()是正确答案,因为大多数MFC类T::GetSize()是正确的,因为CString它是T::GetLength().
我希望有一个像:
template <typename T> auto size(const T & t)
Run Code Online (Sandbox Code Playgroud)
...评估正确的成员函数调用.
看起来应该有一种简单的方法来调用一个traits模板,在T该模板上有一个size(const T & t)成员,它本身使用SFINAE存在或不存在,如果它存在,那么根据定义调用一个适当的方法t.size_function()来返回元素的数量.那个例子T.
我可以编写一个精心设计的has_member类型 - 特征模板 - 在stackoverflow上有一些例子 - 所有这些都让我觉得很复杂"必须有一个更简单的方法".使用C++ 17,似乎应该轻松优雅地解决这个问题?
这里和这里的这些讨论似乎使用了一个不优雅的解决方案,其中一些答案使用预处理器宏来完成工作.这还有必要吗?
但是......当然,必须有一种方法可以使用这样一个事实,即在a上调用正确的成员函数T是可编译的,并且调用错误的函数无法编译 - 不能直接用于创建正确的类型特征包装器给定的类型T?
我想要的是:
template <typename T>
auto size(const T & collection) …Run Code Online (Sandbox Code Playgroud)