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++17作为@ S.M在/std::c++17
模式下编译。已注意到;请注意,某些C ++ 17功能可能会破坏现有代码。此外,@ milesbudnek已经注意到,截至今天,MSVC不支持所需的功能。
如果你不能使用C ++ 17模式,你可以在c++14 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)...);
}
它仅在C ++ 17中有效。尝试使用Project - > Properties - > C ++ - > Language下的标志/std:c++17
在Visual Studio 2017中编译它。请注意,从Visual Studio 2017.3开始提供C ++ 17。
这取决于三个独立的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
。
在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)...};
}