Bre*_*ier 3 c++ templates ambiguity sfinae c++11
编辑:发布我自己的答案,保留原来接受的答案...让我思考别名.
编辑:我的问题是针对在SFINAE(或其他)上下文中区分模糊性与成员var/func存在的可能性.我的问题不是关于如何制作一个has_member模板,而是关于检测模糊与存在之间的区别
是否有可能设置部分特化,以区分何时以不明确的方式访问成员(派生类的基础都具有成员)vs成员是否存在(派生类的基础都不具有成员) ?我只有在检测到歧义时才需要返回true ,但如果根本没有成员,或者只存在一个类,则需要返回true .这是我到目前为止所返回的,它对于模糊性(我想要的)返回true,对于只有一个具有该成员的类(也是我想要的)返回false,但如果两个类都没有该成员则返回true(argh!)
//for the sake of this example, ClassOne comes from a lib I don't control
struct ClassOne {
//some unknown members in here...
};
struct ClassTwo {
string member_var;
};
template<typename A>
struct helper : std::true_type {};
template<typename A, typename B>
struct merged_class : public A, public B {};
template<typename T, typename = void>
struct has_member_var : std::true_type {
//Member request ambiguous or neither class has member.
//I want to catch these conditions separately,
//but this one template catches both :(
const int status = 1;
};
template<typename T>
struct has_member_var<
T
, typename std::enable_if<
//The next line results in either ambiguous member request error
//if both classes have the member OR
//member does not exist error if neither class has the member
//...how to tell the difference in the type of error?
helper<decltype(T::member_var)>::value
, T
>::type
> : std::false_type {
const int status = 2; //only one class has member
};
//This next one I have no idea how to do, if it's even possible.
//I'd like a third specialization that will match either the
//ambiguous condition or the member only existing in one of the
//base classes.
template<typename T>
struct has_member<
T
, typename std::enable_if<
some_freaky_magic<decltype(T::foo)>::true_value
, T
>::type
> : std::true_type {
const int status = 3;
};
Run Code Online (Sandbox Code Playgroud)
期望的用法:
switch(has_member<merged_class<ClassOne, ClassTwo>>::status) {
case 1:
cout << "member ambiguity";
break;
case 2:
cout << "member non-existence";
break;
case 3:
cout << "member existence for only one base";
break;
}
Run Code Online (Sandbox Code Playgroud)
好吧,我想我设法采用表达SFINAE方法并添加类型扣除.这是一个非常粗暴地被黑客攻击的答案,似乎做了一些有用的事情(参见底部的用法示例).
(演示文稿可能会更加简洁和干净,但这样你就可以看出它分为几步.)
用途: conflicting_X<A, B>::value为真当且仅当A,并B有一个名为成员x 和该成员不同(严格,不腐烂)的类型.可以用conflicting_X<A, B>::both和决定中间问题,例如是否为两个类定义成员has_X<T>::value.
#include <iostream>
#include <type_traits>
#include <typeinfo>
// has_X is taken straight from the other topic
template <typename T>
struct has_X
{
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
// Here we go...
template <typename T>
struct XType
{
typedef decltype(T::x) type;
};
template <bool, typename S, typename T>
struct compare_X
{
static const bool value = false;
};
template <typename S, typename T>
struct compare_X<true, S, T>
{
// Note that we don't decay, we want equality on the nose.
static const bool value = ! std::is_same<typename XType<S>::type, typename XType<T>::type>::value;
};
template <typename S, typename T>
struct conflicting_X
{
// We split this up so that XType is only instantiated if T::x really exists.
// You may also use conflicting_X::both as a useful datum.
static const bool both = has_X<S>::value && has_X<T>::value;
static const bool value = compare_X<both, S, T>::value;
};
/*** Example ***/
struct A { int x; };
struct B { int X; };
struct C { double x; };
void f(double) { }
int main() {
std::cout << has_X<A>::value << std::endl; // 1
std::cout << has_X<B>::value << std::endl; // 0
std::cout << "Conflict A/B? " << conflicting_X<A, B>::value << std::endl;
std::cout << "Conflict A/C? " << conflicting_X<A, C>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
781 次 |
| 最近记录: |