问题
I'm trying to deduce the greater of two template arguments at compile time. Both template arguments are of type size_t.
I have a templated type, SomeType, which takes a size_t as it's template argument. I then have a function that takes two SomeType parameters with different template size_t's and i want the return type to be a SomeType with its templated size_t to be the greater of the two input size_t sizes.
template <size_t d> struct SomeType {...}
template<size_t d1, size_t d2>
SomeType<the_larger_of_d1_and_d2> Func(SomeType<d1> A, SomeType<d2> B)
{
...
}
Is this possible?
回答1:
You can compute the type directly, no need for SFINAE:
template<size_t d1, size_t d2>
SomeType<(d1 > d2 ? d1 : d2)> Func(SomeType<d1> A, SomeType<d2> B)
{
…
}
回答2:
The solution by @KonradRudolph is correct of course. But if you want to delve further in to template metaprogramming, it would pay-off very quickly to learn Boost.MPL. It provides a whole battery of convenience functions. E.g. your question can be solved like
#include <iostream>
#include <boost/mpl/int.hpp>
#include <boost/mpl/max.hpp>
template<size_t d>
struct SomeType
:
boost::mpl::int_<d>
{};
template<size_t d1, size_t d2>
typename boost::mpl::max<SomeType<d1>, SomeType<d2> >::type
Func(SomeType<d1> A, SomeType<d2> B)
{
return typename boost::mpl::max<SomeType<d1>, SomeType<d2> >::type();
}
int main()
{
SomeType<2> st2;
SomeType<3> st3;
boost::mpl::max<SomeType<2>, SomeType<3> >::type res = Func(st2, st3);
std::cout << res.value;
}
Live Example.
Some notes:
- letting
SomeType
inherit fromboost::mpl::int_
endows it with atype
andvalue
, as well as some convenient tags. This makes it very easy to re-use other metafunctions from Boost.MPL - the
boost::mpl::max
does the same ternary trick behind the scenes. It is more readible IMO, and if you ever want to change to another condition it's easy to do so. - there is a bit of a learning curve for Boost.MPL, but the tutorial at the linked documentation should get you started.
回答3:
If you can make use of the c++11 standard, you can use SFINAE standard support:
template<size_t one, size_t two>
struct larger {
static constexpr typename std::enable_if<(one > two), size_t>::type value() {
return one;
}
static constexpr typename std::enable_if<(two >= one, size_t>::type value() {
return two;
}
};
Then
template<size_t d1, size_t d2>
SomeType<larger<d1, d2>::value()> Func(SomeType<d1> A, SomeType<d2> B)
{
...
}
回答4:
As I'm constantly have to look up myself (my older code) about that question again and again, I've decided to make a GIT gist, and compilation sample that allows (at least me) to quickly access some 'template' code (pun intended), to play with the meta-programmed conditional type selection stuff (also working for the 'old' c++03 standard):
Selector declaration:
template<typename FalseType, typename TrueType, bool condition>
struct ConditionalTypeSelector {
typedef void ResultType;
};
Selector specialization(s):
template<typename FalseType, typename TrueType>
struct ConditionalTypeSelector<FalseType,TrueType,false> {
typedef FalseType ResultType;
};
template<typename FalseType, typename TrueType>
struct ConditionalTypeSelector<FalseType,TrueType,true> {
typedef TrueType ResultType;
};
Selected types:
struct A {
unsigned char member;
};
struct B {
int member;
};
struct C {
long long member;
};
Testing:
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
cout << typeid
( ConditionalTypeSelector
< A,B,(sizeof(A) > sizeof(B))>::ResultType
).name() << endl;
cout << typeid
( ConditionalTypeSelector
<A,B,(sizeof(B) > sizeof(A)) >::ResultType
).name() << endl;
cout << typeid
( ConditionalTypeSelector
< A,C,(sizeof(A) > sizeof(C))>::ResultType
).name() << endl;
cout << typeid
( ConditionalTypeSelector
< C,B,true>::ResultType
).name() << endl;
cout << typeid
( ConditionalTypeSelector
< C,A,false>::ResultType
).name() << endl;
return 0;
}
It's pretty easy to change this template
to use e.g. an enum
type for specialized selections, or whatever else constant condition known at compile time should be checked.
来源:https://stackoverflow.com/questions/21711433/template-argument-calculation-at-compile-time