Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 获取模板参数的typedef,或者获取类型本身失败_C++_Templates_C++11_Sfinae - Fatal编程技术网

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; 
};