我已经看到这个问题允许人们检查是否存在成员函数,但我试图找出一个类是否有成员类型.
在下面的示例中,两者都评估为"false",但我想找到一种方法,以便has_bar<foo1>::value计算为false,并has_bar<foo2>::value计算为true.
这可能吗?
#include <iostream>
struct foo1;
struct foo2 { typedef int bar; };
template <typename T>
class has_bar
{
typedef char yes;
typedef long no;
template <typename C> static yes check( decltype(&C::bar) ) ;
template <typename C> static no check(...);
public:
enum { value = sizeof(check<T>(0)) == sizeof(yes) };
};
int main()
{
std::cout << has_bar<foo1>::value << std::endl;
std::cout << has_bar<foo2>::value << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:实施专业化以回应以下答案: …
场景:
我有多种类型可以归类为序列容器.
所有序列容器都是数据结构,但并非每个数据结构都是序列容器.
以下是代码中说明的示例.此示例中涉及的唯一"重要类型"是Array_T.它分为两类:它是一个序列容器,由于所有序列容器都是数据结构,因此它又是一个数据结构.
//A sequence container type
class Array_T{};
//A type trait for that particular sequence container
template <typename T> struct Is_Array { static const bool value = false; };
template <> struct Is_Array<Array_T> { static const bool value = true; };
//A type trait to identify all of the sequence containers
template <typename T> struct Is_A_Sequence_Container { static const bool value = Is_Array<T>::value
/* would probably "or" together more sequence types, but we only have Array_T in this …Run Code Online (Sandbox Code Playgroud) 我一直在尝试根据是否operator<<(std::ostream&, const T&)存在过载来在两个模板化函数之间进行选择.
例:
template <typename T, typename std::enable_if</* ? */, int>::type = 0>
std::string stringify(const T& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
template <typename T, typename std::enable_if</* ? */, int>::type = 0>
std::string stringify(const T& t)
{
return "No overload of operator<<";
}
struct Foo { };
int main()
{
std::cout << stringify(11) << std::endl;
std::cout << stringify(Foo{}) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这可能吗?如果是这样,你会如何解决这个问题?
一点概述.我正在编写一个提供强大typedef的类模板; 通过强类型定义我与一个只声明别名的常规typedef形成对比.提出一个想法:
using EmployeeId = StrongTypedef<int>;
Run Code Online (Sandbox Code Playgroud)
现在,强类型定义和隐式转换有不同的思想流派.其中一所学校说:并非每个整数都是EmployeeId,但每个EmployeeId都是一个整数,所以你应该允许从EmployeeId到整数的隐式转换.你可以实现这个,并编写如下内容:
EmployeeId x(4);
assert(x == 4);
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为x隐式转换为整数,然后使用整数相等比较.到现在为止还挺好.现在,我想用一个整数向量来做这个:
using EmployeeScores = StrongTypedef<std::vector<int>>;
Run Code Online (Sandbox Code Playgroud)
所以我可以这样做:
std::vector<int> v1{1,2};
EmployeeScores e(v1);
std::vector<int> v2(e); // implicit conversion
assert(v1 == v2);
Run Code Online (Sandbox Code Playgroud)
但我还是不能这样做:
assert(v1 == e);
Run Code Online (Sandbox Code Playgroud)
这不起作用的原因是因为如何std::vector定义其等式检查,基本上(模数标准):
template <class T, class A>
bool operator==(const vector<T,A> & v1, const vector<T,A> & v2) {
...
}
Run Code Online (Sandbox Code Playgroud)
这是一个功能模板; 因为它在早期的查找阶段被丢弃,所以不允许将隐式转换为vector的类型进行比较.
定义平等的另一种方式是这样的:
template <class T, class A = std::allocator<T>>
class vector {
... // body
friend bool operator==(const vector & v1, const vector …Run Code Online (Sandbox Code Playgroud) 我有一个函数模板,它接受许多不同的类型作为输入。在这些类型中,只有其中一种具有getInt()功能。因此,我希望代码仅针对该类型运行该函数。请提出一个解决方案。谢谢
#include <type_traits>
#include <typeinfo>
class X {
public:
int getInt(){
return 9;
}
};
class Y{
};
template<typename T>
void f(T& v){
// error: 'class Y' has no member named 'getInt'
// also tried std::is_same<T, X>::value
if(typeid(T).name() == typeid(X).name()){
int i = v.getInt();// I want this to be called for X only
}
}
int main(){
Y y;
f(y);
}
Run Code Online (Sandbox Code Playgroud) 如果参数是C++函数对象(仿函数),我如何静态推导出?
template <typename F>
void test(F f) {}
Run Code Online (Sandbox Code Playgroud)
我试过了is_function<F>::value,但这不起作用.它似乎也没有is_functor特质,所以也许这是不可能的.我似乎只是在寻找一个特定的成员函数,在本例中是函数调用操作符:F::operator().
我正在尝试检查一个类是否有方法operator==.我在这里找到了一个SFINAE的解决方案,它与我制作的课程一起工作正常.
它看起来像这样:
template <typename T>
class comparable
{
typedef char one;
typedef long two;
template <typename C> static one test( typeof(&C::operator==) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试:
std::cout << comparable<int>::value << std::endl;
Run Code Online (Sandbox Code Playgroud)
然后它返回false,而我期望它返回true.为什么是这样 ?
这个问题的灵感来自于这个答案.我想知道在给定标准中简化它的最佳方法是什么.一个我知道并且个人使用/仍在使用,因为C++ 14是宏REQUIRES(x):
定义:
template<long N>
struct requires_enum
{
enum class type
{
none,
all
};
};
#define REQUIRES(...) requires_enum<__LINE__>::type = \
requires_enum<__LINE__>::type::none, \
bool PrivateBool = true, \
typename std::enable_if<PrivateBool && (__VA_ARGS__), int>::type = 0
Run Code Online (Sandbox Code Playgroud)
即使对于非模板化函数调用也使用:
template<REQUIRES(sizeof(int)==4)>
int fun() {return 0;}
int main()
{
fun(); //only if sizeof(int)==4
}
Run Code Online (Sandbox Code Playgroud)
REQUIRES我使用的原文来自这篇文章.
还有什么好的技巧?
SFINAE的一些例子需要一些或很长时间才能理解读者刚开始使用SFINAE的冒险:
Pre-C++ 11 SFINAE示例(来源):
template <typename T>
struct has_typedef_foobar {
// Types "yes" and "no" are guaranteed to have different …Run Code Online (Sandbox Code Playgroud) 我想有几个重载的全局to_string()函数,它们采用某种类型T并将其转换为字符串表示形式.对于一般情况,我希望能够写:
template<typename T,class OutputStringType> inline
typename enable_if<!std::is_pointer<T>::value
&& has_insertion_operator<T>::value,
void>::type
to_string( T const &t, OutputStringType *out ) {
std::ostringstream o;
o << t;
*out = o.str();
}
Run Code Online (Sandbox Code Playgroud)
has_insertion_operator到目前为止,我的实施是:
struct sfinae_base {
typedef char yes[1];
typedef char no[2];
};
template<typename T>
struct has_insertion_operator : sfinae_base {
template<typename U> static yes& test( U& );
template<typename U> static no& test(...);
static std::ostream &s;
static T const &t;
static bool const value = sizeof( test( s << t ) …Run Code Online (Sandbox Code Playgroud) 我有一个非常简单的问题:某个地方有一个功能
int size (const C & c)
Run Code Online (Sandbox Code Playgroud)
至少可以通过参数依赖的名称查找找到它.现在的问题是:
struct B
{
int size () { /* ... */ }
void doSomething (const C & c)
{
int x = size (c); // <----------- problem!
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为名称查找在找到成员函数后停止.
我必须在指示的行中写什么,以便不会尝试调用成员函数,但是,如果成员函数不存在,编译器会做什么呢?
请注意,解决方案不是写入::size,因为这会阻止依赖于参数的名称查找,并且只有在我知道size声明的位置时才有效.
进一步复杂化:
我知道对于T我使用下面模板化成员函数的每个相关类型B::doSomething,某处会有一个函数
int size (const T & t)
Run Code Online (Sandbox Code Playgroud)
至少可以通过参数依赖的名称查找找到它.B看起来如下:
struct B
{
int size () { /* ... */ }
template<class T>
void …Run Code Online (Sandbox Code Playgroud)