C++ 获取模板参数的typedef,或者获取类型本身失败
我正试图从我定义的类(C++ 获取模板参数的typedef,或者获取类型本身失败,c++,templates,c++11,sfinae,C++,Templates,C++11,Sfinae,我正试图从我定义的类(ValueTypetypedef)中获取typedef指向的类型。但是,如果失败,我希望它返回给定的类型(例如,如果我给它一个double,我希望它返回一个double)。这就是我到目前为止所做的: struct myClass { typedef double ValueType; }; template < typename V, typename U = typename V::ValueType> struct base_type { typedef
ValueType
typedef)中获取typedef指向的类型。但是,如果失败,我希望它返回给定的类型(例如,如果我给它一个double
,我希望它返回一个double
)。这就是我到目前为止所做的:
struct myClass { typedef double ValueType; };
template < typename V, typename U = typename V::ValueType>
struct base_type { typedef U type; };
template < typename V >
struct base_type< V, V > { typedef V type; };
static_assert( std::is_same < typename base_type< myClass >::type , double >::value,
"base_type doesn't work" ); //This works.
static_assert( std::is_same < typename base_type< double >::type , double >::value,
"base_type doesn't work" ); //This returns "error: 'double' is not a class, struct, or union type"
struct myClass{typedef double ValueType;};
模板
结构base_type{typedef U type;};
模板
结构base_type{typedef V type;};
静态断言(std::is_same::type,double>::value,
“基本类型不工作”)//这很有效。
静态断言(std::is_same::type,double>::value,
“基本类型不工作”)//返回“错误:'double'不是类、结构或联合类型”
但是,这不起作用,第二个静态断言失败。显然,第二个定义从未被调用,但我不确定为什么(它肯定比第一个匹配得更好)
有什么想法吗?来自
以下内容适合我,我认为它符合你的要求
#include <type_traits>
template <typename T>
struct has_typedef_ValueType {
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::ValueType*);
template <typename>
static no& test(...);
// If the "sizeof" the result of calling test<T>(0) would be equal to the sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
struct myClass { typedef double ValueType; };
template < class V, bool b = has_typedef_ValueType<V>::value >
struct base_type { typedef typename V::ValueType type; };
template < typename V>
struct base_type <V, false> { typedef V type; };
static_assert( std::is_same < typename base_type< myClass >::type , double >::value, "base_type doesn't work" ); //This works.
static_assert( std::is_same < typename base_type< double >::type , double >::value, "base_type doesn't work" ); //This returns "error: 'double' is not a class, struct, or union type"
int main() {}
#包括
模板
结构具有_typedef_ValueType{
//“是”和“否”类型保证有不同的尺寸,
//具体地说,sizeof(yes)==1和sizeof(no)==2。
typedef char yes[1];
typedef字符编号[2];
模板
静态是&测试(typename C::ValueType*);
模板
静态no&test(…);
//如果“sizeof”,则调用测试(0)的结果将等于sizeof(是),
//第一个重载起作用,T有一个名为foobar的嵌套类型。
静态常量布尔值=sizeof(测试(0))==sizeof(是);
};
结构myClass{typedef double ValueType;};
模板
结构基_类型{typedef typename V::ValueType;};
模板
结构base_type{typedef V type;};
静态断言(std::is_same::type,double>::value,“base_type不工作”)//这很有效。
静态断言(std::is_same::type,double>::value,“base_type不工作”)//返回“错误:'double'不是类、结构或联合类型”
int main(){}
您必须使用一个函数来实现有效的SFINAE
以下是新的C++11功能的外观:
template <typename T> auto get_base_type(int) -> typename T::ValueType;
template <typename T> auto get_base_type(...) -> T;
template <typename T>
struct base_type { using type = decltype(get_base_type<T>(0)); };
模板自动获取基本类型(int)->typename T::ValueType;
模板自动获取基本类型(…)->T;
模板
结构base_type{using type=decltype(get_base_type(0));};
一个永远真实的班级
现在,
void
技巧有一些问题。但是我发现它非常通用。double
不会实例化您的专业化,因为只有当base\u type
传递两种类型并且两者都相同时,才会调用该专业化。第二种类型是可选的,但如果没有提供,则会用默认的typename V::ValueType
填充,当然,对于double::ValueType
来说,这是失败的
为完整起见,您的base\u类型
专业化将被实例化为以下类型:
struct foo { typedef foo ValueType; };
static_assert(std::is_same<base_type<foo>::type, foo>::value, "Failed");
struct foo{typedef foo ValueType;};
静态断言(std::is_same::value,“Failed”);
或者
template < typename V, typename = void>
struct base_type { typedef V type; };
template < typename V >
struct base_type< V,
typename base_type<void, typename V::ValueType>::type > {
typedef typename V::ValueType type;
};
模板
结构base_type{typedef V type;};
模板
结构基本类型{
typedef typename V::ValueType类型;
};
我们多么喜欢这些粗俗丑陋的斯芬纳黑客:)@SteveJessop这是不对的。下面的多个答案使用了SFINAE类内模板部分专门化。请等待C++14或C++17中的概念支持@雅克:我真的很期待。老实说,我希望将concepts lite合并到GCC 4.8的树中,这会使事情变得更好。首先,
void
参数有点难看,您可以通过传入int
(或其他)绕过专门化。因此,您需要像template struct foo:details::foo_impl{}
那样包装它,这样用户就不会“看到”void参数。接下来,您需要确保只有一个专门化是有效的,如果在添加更多专门化(&&!&&&&&!
)时,逻辑变得过于臃肿,则会使启用\u——它的伸缩性不好。最后,生成的错误消息并不是那么好。
struct foo { typedef foo ValueType; };
static_assert(std::is_same<base_type<foo>::type, foo>::value, "Failed");
template < typename V, typename = void>
struct base_type { typedef V type; };
template < typename V >
struct base_type< V,
typename base_type<void, typename V::ValueType>::type > {
typedef typename V::ValueType type;
};