我试图为值列表中的值创建索引元查找器.
这是代码:
#include<type_traits>
#include<utility>
template <auto... Values>
struct ValueTplList;
template <auto>
constexpr int MetaFindV(int ind)
{ // not found case
return -1;
}
template <auto NeedleV, auto V, auto... Vs>
constexpr int MetaFindV(int ind = 0)
{
if constexpr (std::is_same_v<decltype(NeedleV), decltype(V)>)
{
return NeedleV == V ? ind : MetaFindV<NeedleV, Vs...>(ind + 1);
}
else
{
return MetaFindV<NeedleV, Vs...>(ind + 1);
}
}
// main
template <auto, typename>
struct MetaIndexOfV;
// destructurer
template <auto V, template<auto...> class Tmpl, auto... Vs>
struct MetaIndexOfV<V, Tmpl<Vs...> >
: std::integral_constant< int, MetaFindV<V, Vs...>() >
{};
// template variable version of it:
template <auto V, typename TemplInst>
constexpr int metaFindV_v = MetaIndexOfV<V, TemplInst>::value;
// tests
static_assert(metaFindV_v< 0, ValueTplList<0> > == 0 );
static_assert(metaFindV_v< 5, ValueTplList<0> > == -1);
static_assert(metaFindV_v< 0, ValueTplList<nullptr, 0> > == 1);
static_assert(metaFindV_v< 2, ValueTplList<1, (long)2, 2, 3, 4> > == 2);
static_assert(metaFindV_v< -1, ValueTplList<-2, -1, 42> > == 1);
在这里找到行为:
https://godbolt.org/z/ukwxpN
你会发现这与gcc 7及以上版本以及clang 5及以上版本编译良好.
我想知道我是否真的通过MSVC强制要求这种仇恨的标准做错了.我现在不能自己看到它:'(
它说:
(30): error C2672: ‘MetaFindV’: no matching overloaded function found > (31): note: see reference to class template instantiation ‘MetaIndexOfV>’ being compiled
(30): error C2975: ‘V’: invalid template argument for ‘MetaFindV’, expected compile-time constant expression
(12): note: see declaration of ‘V’
(30): error C2977: ‘MetaFindV’: too many template arguments
我认为这是抱怨这条线
:std :: integral_constant< int,MetaFindV< V,Vs …>()>
就像MetaFindV< V,Vs …>()没有匹配功能一样.
(最后注意:如果你更改了typename的所有auto, – 稍微调整一下 – 整个事情开始起作用(但当然只对类型和类型列表而言),即使代码模式完全相同.)
最佳答案 不是答案(对不起:我怀疑这是一个MSVC错误,但我不确定)但是长篇评论.
我提出了一种完全不同的方式来获得你想要的东西:
#include <type_traits>
#include <string>
template <auto... Values>
struct ValueTplList
{ };
template <auto, auto>
struct strongSame : public std::false_type
{ };
template <auto A>
struct strongSame<A, A> : public std::true_type
{ };
template <auto TargetVal, auto ... Values>
constexpr int foo (ValueTplList<Values...> const &)
{
int ind = -1;
(void)( (++ind, strongSame<TargetVal, Values>::value)
|| ... || (++ind, true) );
return std::size_t(ind) == sizeof...(Values) ? -1 : ind;
}
template <auto V, typename TemplInst>
constexpr int metaFindV_v = foo<V>(TemplInst{});
// tests
static_assert(metaFindV_v< 0, ValueTplList<0> > == 0 );
static_assert(metaFindV_v< 5, ValueTplList<0> > == -1);
static_assert(metaFindV_v< 0, ValueTplList<nullptr, 0> > == 1);
static_assert(metaFindV_v< 2, ValueTplList<1, (long)2, 2, 3, 4> > == 2);
static_assert(metaFindV_v< -1, ValueTplList<-2, -1, 42> > == 1);
int main ()
{
}