如果我有一个带有模板参数的算法,比如
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);
有没有办法可以写foo
,这样如果Parameters
缺少某些内容,我就可以提供默认值。例如
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>
如果Prices_type<Parameters>::type
是Parameters::Prices
的成员,Prices
为Parameters
,则std::vector<Parameters::Price>
为{{1}}。
这可能吗?
答案 0 :(得分:1)
这名为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;
}
上面的示例为Foo提供type
int TypeOrDefault
类型成员,为Bar提供float。
您还可以使用模板别名简化使用语法。
template < typename T, typename Default >
using TypeOrDefaultType = typename TypeOrDefault<T,Default>::type;
然后
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;
}
答案 1 :(得分:1)
你可以这样做(标签调度和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;
};
测试它:
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, "");