首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >限制可变模板参数

限制可变模板参数
EN

Stack Overflow用户
提问于 2016-09-23 11:00:11
回答 5查看 7.3K关注 0票数 52

我们可以将可变模板参数限制为某种类型吗?也就是说,实现这样的目标(当然不是真正的C++ ):

代码语言:javascript
复制
struct X {};

auto foo(X... args)

在这里,我的意图是有一个接受可变数量的X参数的函数。

我们最近的发现是:

代码语言:javascript
复制
template <class... Args>
auto foo(Args... args)

但这接受任何类型的参数。

EN

回答 5

Stack Overflow用户

发布于 2016-09-23 12:51:22

C++14

因为C++14也可以使用可变模板、部分专门化和static_assert来实现这一点。例如:

代码语言:javascript
复制
#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>();
}

还可以将checkstd::enable_if_t结合使用作为返回类型,如果出于某些未知原因不想使用static_assert

代码语言:javascript
复制
template<typename... T>
std::enable_if_t<check<std::is_convertible, int, T...>>
f() {
    // ...
}

等等..。

C++11

在C++11中,您还可以设计一个解决方案,在遇到不可接受的类型时立即停止递归。例如:

代码语言:javascript
复制
#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

票数 7
EN

Stack Overflow用户

发布于 2016-09-23 11:43:21

下面的解决方案呢?

--编辑--改进了bolov和Jarod42的建议(谢谢!)

代码语言:javascript
复制
#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)实现它。

票数 4
EN

Stack Overflow用户

发布于 2016-09-23 12:30:07

static_assert和助手模板方法(c++11解决方案)如何:

代码语言:javascript
复制
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的“一条龙”解决方案:

代码语言:javascript
复制
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) {
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39659127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档