[英]Template argument calculation at compile time
I'm trying to deduce the greater of two template arguments at compile time. 我试图在编译时推断出两个模板参数中较大的一个。 Both template arguments are of type size_t.
两个模板参数的类型都是size_t。
I have a templated type, SomeType, which takes a size_t as it's template argument. 我有一个模板类型SomeType,它接受size_t作为模板参数。 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.
然后我有一个函数,它接受两个具有不同模板size_t的SomeType参数,并且我希望返回类型是SomeType,其模板化size_t是两个输入size_t大小中的较大者。
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? 这可能吗?
You can compute the type directly, no need for SFINAE: 您可以直接计算类型,不需要SFINAE:
template<size_t d1, size_t d2>
SomeType<(d1 > d2 ? d1 : d2)> Func(SomeType<d1> A, SomeType<d2> B)
{
…
}
The solution by @KonradRudolph is correct of course. @KonradRudolph的解决方案当然是正确的。 But if you want to delve further in to template metaprogramming, it would pay-off very quickly to learn Boost.MPL .
但是如果你想深入研究模板元编程,那么学习Boost.MPL会很快得到回报。 It provides a whole battery of convenience functions.
它提供了一整套便利功能。 Eg 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: 一些说明:
SomeType
inherit from boost::mpl::int_
endows it with a type
and value
, as well as some convenient tags. SomeType
继承自boost::mpl::int_
赋予它一个type
和value
,以及一些方便的标签。 This makes it very easy to re-use other metafunctions from Boost.MPL boost::mpl::max
does the same ternary trick behind the scenes. boost::mpl::max
在幕后执行相同的三元技巧。 It is more readible IMO, and if you ever want to change to another condition it's easy to do so. If you can make use of the c++11 standard, you can use SFINAE standard support: 如果您可以使用c ++ 11标准,则可以使用SFINAE标准支持:
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)
{
...
}
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): 由于我经常不得不一次又一次地查询自己(我的旧代码)关于这个问题,我决定制作一个GIT要点 ,以及允许(至少我)快速访问某些“模板”代码的编译示例 (双关语),使用元编程的条件类型选择内容(也适用于'旧' c ++ 03标准):
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 eg an enum
type for specialized selections, or whatever else constant condition known at compile time should be checked. 可以很容易地将此
template
更改为使用例如用于专门选择的enum
类型,或者应该检查编译时已知的任何其他常量条件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.