c – MSVC无法使用模板自动参数识别constexpr函数

我试图为值列表中的值创建索引元查找器.

这是代码:

#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 ()
 {
 }
点赞