如何在Visual Studio 2017中支持可变参数模板类型

问题描述 投票:0回答:4

T.C. gave a clever solution here使用了这个对象:

template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;
struct fallback_t { template<class T> fallback_t(T&&) {} };

不幸的是我无法在Visual Studio 2017中编译。我得到错误:

1>警告C4346:'Ts ::()':从属名称不是类型 1>注意:带有'typename'的前缀表示类型 1>注意:请参阅正在编译的类模板实例化'owner :: overload'的引用 1>错误C2143:语法错误:缺少';'在'...'之前 1>错误C2059:语法错误:'...' 1>错误C2238:';'之前的意外令牌 1>错误C2988:无法识别的模板声明/定义 1>错误C2143:语法错误:缺少')'之前'...' 1>错误C2143:语法错误:缺少';'在'...'之前 1>错误C2365:'Ts':重新定义;以前的定义是'模板参数' 1>注意:看'Ts'的声明 1>错误C2238:';'之前的意外令牌 1>错误C2059:语法错误:'...' 1>错误C2059:语法错误:')' 1>错误C2955:'owner :: overload':使用类模板需要模板参数列表 1>注意:看'owner :: overload'的声明 1>错误C2664:'void owner :: bar :: :: operator()(owner :: fallback_t)const':无法将参数1从'owner :: fallback_t'转换为'owner :: fallback_t' 1>注意:使用未定义类型'owner :: fallback_t' 1>注意:请参阅'owner :: fallback_t'的声明 1>错误C2672:'owner :: findObject':找不到匹配的重载函数 1>错误C2780:'void owner :: findObject(int,const T&)':需要2个参数 - 提供1个 1>注意:请参阅'owner :: findObject'的声明

有什么技巧可以让Visual Studio尊重可变参数模板吗?

c++ visual-studio templates metaprogramming
4个回答
1
投票

您可以尝试使用作为@ S.M在/std::c++17模式下编译。已注意到;请注意,某些C ++ 17功能可能会破坏现有代码。此外,@ milesbudnek已经注意到,截至今天,MSVC不支持所需的功能。

如果你不能使用C ++ 17模式,你可以在 in this SO answer中实现它。

我做了一些改变:

template <class... Fs>
struct overload_t;

// zero
template<>
struct overload_t<> {};

// >1
template <class F0, class... Frest>
struct overload_t<F0, Frest...> :
  F0,
  overload_t<Frest...>
{
    overload_t(F0 f0, Frest... rest) :
      F0(std::move(f0)), overload_t<Frest...>(std::move(rest)...)
   {}

    using F0::operator();
    using overload_t<Frest...>::operator();
};

// 1
template <class F0>
struct overload_t<F0> : F0
{
    overload_t(F0 f0) : F0(std::move(f0)) {}

    using F0::operator();
};

template <class... Fs>
auto overload(Fs... fs)
{
  return overload_t<Fs...>(std::move(fs)...);
}

2
投票

它仅在C ++ 17中有效。尝试使用Project - > Properties - > C ++ - > Language下的标志/std:c++17在Visual Studio 2017中编译它。请注意,从Visual Studio 2017.3开始提供C ++ 17。


2
投票

这取决于三个独立的C ++ 17功能:

  • 可变参数使用声明(支持包扩展)
  • 与基类聚合
  • 类模板参数推导

通常的前C ++ 17解决方法是第一个是递归继承(为简单起见省略了转发):

template<class T, class... Ts> 
struct overload : T, overload<Ts...> {
    using T::operator();
    using overload<Ts...>::operator();
    overload(T t, Ts... ts) : T(t), overload<Ts...>(ts...) {}
};

template<class T> 
struct overload<T> : T {
    using T::operator();
    overload(T t) : T(t) {}
};

template<class...Ts> 
overload<Ts...> make_overload(Ts... ts) {
    return overload<Ts...>(ts...); 
}

如果编译器不支持具有基类的聚合,则需要构造函数;如果编译器不支持类模板的模板参数推导,则需要make_overload


1
投票

在C ++ 14中,它将是这样的:

template <typename ... Ts> struct overload;

template <typename T>
struct overload<T> : T
{
    template <typename U>
    overload(U&& u) : T(std::forward<U>(u)) {}

    using T::operator();
};


template <typename T, typename ... Ts>
struct overload<T, Ts...> : overload<T>, overload<Ts...>
{
    template <typename U, typename ... Us>
    overload(U&& arg, Us&&... args) : overload<T>(std::forward<U>(arg)),
                                      overload<Ts...>(std::forward<Us>(args)...) {}

    using overload<T>::operator();
    using overload<Ts...>::operator();
};

template<class... Ts>
overload<std::decay_t<Ts>...> make_overload(Ts&&... args)
{
    return {std::forward<Ts>(args)...};
}

Demo

© www.soinside.com 2019 - 2024. All rights reserved.