我们可以将可变模板参数限制为某种类型吗?也就是说,实现这样的目标(当然不是真正的C++ ):
struct X {};
auto foo(X... args)在这里,我的意图是有一个接受可变数量的X参数的函数。
我们最近的发现是:
template <class... Args>
auto foo(Args... args)但这接受任何类型的参数。
发布于 2016-09-23 12:51:22
C++14
因为C++14也可以使用可变模板、部分专门化和static_assert来实现这一点。例如:
#include <type_traits>
template<template<typename...> class, typename...>
constexpr bool check = true;
template<template<typename...> class C, typename U, typename T, typename... O>
constexpr bool check<C, U, T, O...> = C<T, U>::value && check<C, U, O...>;
template<typename... T>
void f() {
// use std::is_convertible or whichever is the best trait for your check
static_assert(check<std::is_convertible, int, T...>, "!");
// ...
}
struct S {};
int main() {
f<int, unsigned int, int>();
// this won't work, for S is not convertible to int
// f<int, S, int>();
}还可以将check与std::enable_if_t结合使用作为返回类型,如果出于某些未知原因不想使用static_assert:
template<typename... T>
std::enable_if_t<check<std::is_convertible, int, T...>>
f() {
// ...
}等等..。
C++11
在C++11中,您还可以设计一个解决方案,在遇到不可接受的类型时立即停止递归。例如:
#include <type_traits>
template<bool...> struct check;
template<bool... b> struct check<false, b...>: std::false_type {};
template<bool... b> struct check<true, b...>: check<b...> {};
template<> struct check<>: std::true_type {};
template<typename... T>
void f() {
// use std::is_convertible or whichever is the best trait for your check
static_assert(check<std::is_convertible<int, T>::value...>::value, "!");
// ...
}
struct S {};
int main() {
f<int, unsigned int, int>();
// this won't work, for S is not convertible to int
// f<int, S, int>();
}如前所述,您也可以在返回类型中或在任何您想要的地方使用check。
发布于 2016-09-23 11:43:21
下面的解决方案呢?
--编辑--改进了bolov和Jarod42的建议(谢谢!)
#include <iostream>
template <typename ... Args>
auto foo(Args... args) = delete;
auto foo ()
{ return 0; }
template <typename ... Args>
auto foo (int i, Args ... args)
{ return i + foo(args...); }
int main ()
{
std::cout << foo(1, 2, 3, 4) << std::endl; // compile because all args are int
//std::cout << foo(1, 2L, 3, 4) << std::endl; // error because 2L is long
return 0;
}您可以声明foo()来接收所有类型的参数(Args ... args),但是(递归地)只为一种类型(本例中的int)实现它。
发布于 2016-09-23 12:30:07
static_assert和助手模板方法(c++11解决方案)如何:
template <bool b>
int assert_impl() {
static_assert(b, "not convertable");
return 0;
}
template <class... Args>
void foo_x(Args... args) {
int arr[] {assert_impl<std::is_convertible<Args, X>::value>()...};
(void)arr;
}另一个c++11 --这个使用了基于sfinae的“一条龙”解决方案:
template <class... Args,
class Enable = decltype(std::array<int, sizeof...(Args)>{typename std::enable_if<std::is_convertible<Args, X>::value, int>::type{}...})>
void foo_x(Args... args) {
}https://stackoverflow.com/questions/39659127
复制相似问题