[英]Can I create default types for missing template member types?
If I have an algorithm with template parameters, something like 如果我有一个带模板参数的算法,就像
struct DemoParameters
{
typedef float Price;
typedef std :: list <Price> Prices;
}
template <typename Parameters>
void foo (int arg)
{
typename Parameters :: Prices prices = ...;
// blah
}
foo <DemoParameters> (123);
Is there a way I can write foo
so that if something is missing from Parameters
I can supply a default. 有没有办法可以编写
foo
这样如果Parameters
缺少某些内容,我可以提供默认值。 For example 例如
struct PartialParameters
{
typedef float Price;
// Prices is missing
}
template <typename Parameters>
void foo (int arg)
{
Prices_type<Parameters>::type prices = ...;
}
foo<DemoParameters> (123); // will use list<Price>
foo<PartialParameters> (123); // will use vector<Price>
Where Prices_type<Parameters>::type
is Parameters::Prices
if Prices
is a member of Parameters
, or std::vector<Parameters::Price>
otherwise. 其中
Prices_type<Parameters>::type
是Parameters::Prices
如果Prices
是Parameters
的成员,或者std::vector<Parameters::Price>
否则。
Is this possible? 这可能吗?
This is named SFINAE : 这被命名为SFINAE:
#include <iostream>
struct Foo {
using Type = int;
};
struct Bar {
};
template <typename T, typename Default >
struct TypeOrDefault {
template <typename U>
static auto call( int ) -> typename U::Type;
template <typename U>
static auto call(...) -> Default;
using type = decltype( call<T>( 1 ) );
};
int main() {
std::cout << std::is_same<int,typename TypeOrDefault<Foo,float>::type > ::value << std::endl;
std::cout << std::is_same<int,typename TypeOrDefault<Bar,float>::type > ::value << std::endl;
}
The example above give to the type
type member of TypeOrDefault
int for Foo and float for Bar. 上面的示例为Foo提供了
TypeOrDefault
int的type
类型成员,为Bar提供了float。
you can also simplify the syntax on use with a template alias. 您还可以使用模板别名简化使用语法。
template < typename T, typename Default >
using TypeOrDefaultType = typename TypeOrDefault<T,Default>::type;
then 然后
int main() {
std::cout << std::is_same<int,TypeOrDefaultType<Foo,float> > ::value << std::endl;
std::cout << std::is_same<int,TypeOrDefaultType<Bar,float> > ::value << std::endl;
}
You may do something like this (Tag dispatching and SFINAE): 你可能会做这样的事情(标签调度和SFINAE):
template <typename T> struct has_Prices
{
private:
template <typename U> static std::uint8_t check(typename U::Prices*);
template <typename U> static std::uint16_t check(...);
public:
static const bool value = sizeof(check<T>(0)) == sizeof(std::uint8_t);
};
template <typename T, bool = has_Prices<T>::value> struct Prices_type;
template <typename T>
struct Prices_type<T, true>
{
typedef typename T::Prices type;
};
template <typename T, bool>
struct Prices_type
{
typedef std::vector<typename T::Price> type;
};
Test it: 测试一下:
struct DemoParameters
{
typedef float Price;
typedef std :: list <Price> Prices;
};
struct PartialParameters
{
typedef float Price;
// Prices is missing
};
static_assert(std::is_same<std::list<float>, Prices_type<DemoParameters>::type>::value, "");
static_assert(std::is_same<std::vector<float>, Prices_type<PartialParameters>::type>::value, "");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.