c++ - 模板变量是否可以用作模板参数(类似于类模板)?

标签 c++ templates parameters c++17

C++17 为非类型模板参数提供了 auto 关键字。有没有办法将其组合到模板模板参数中,然后可以将其与模板变量一起用作参数?

template <template <typename> auto X> // <-- This seems to be illegal
struct Foo
{
};

背景:
我想为 type_vector 类实现一个 copy_if。由于我想使用的所有条件都可以作为模板变量使用,因此实现它的一种方法是:

template <typename Container, 
          template <typename> auto Condition> // If this were allowed
struct copy_if;

template <typename... Ts,
          template <typename> auto Condition>
struct copy_if<type_vector<Ts...>, Condition>
{
  using type = decltype(
      (type_vector<>{} + ... + 
          std::conditional_t<Condition<Ts>, 
                             type_vector<Ts>,
                             type_vector<>>{}));
};

当然,我可以将所有变量包装到具有值的模板结构中,但我宁愿避免这种情况。

最佳答案

也许额外的谓词参数(自 c++17 起可用的 constexpr lambda)确定参数是否符合您的变量模板就足够了吗?

#include <algorithm>
#include <iostream>
#include <string>
#include <type_traits>

template <class T>
constexpr bool condition = true;

template <>
constexpr bool condition<int> = false;


template <class T>
struct tag { 
   using type = T;
};

template <class... Ts>
struct type_vector {
    template <class... Ts2>
    type_vector<Ts..., Ts2...> operator+(type_vector<Ts2...>);
};

template <class... Ts,
          class Predicate>
auto copy_if(type_vector<Ts...>, Predicate p)
{
  return decltype(
      (type_vector<>{} + ... + 
          std::conditional_t<p(tag<Ts>{}), 
                             type_vector<Ts>,
                             type_vector<>>{})){};
};

int main() {
    auto predicate = [](auto x){ return condition<typename decltype(x)::type>;};
    std::cout << typeid(decltype(copy_if(type_vector<int, float, double>{}, predicate))).name() << std::endl;
}

c++过滤输出:

type_vector<float, double>

[live demo]


编辑:

在某些情况下,使用人工标记来分派(dispatch)参数类型可能会被认为很麻烦。如果您想避免它,还有另一种方法。这实际上避免了调用 lambda 的 operator() 模板,它只是实例化它以评估结果类型(应该等同于 std::true_typestd::false_type):

#include <algorithm>
#include <iostream>
#include <string>
#include <type_traits>

template <class T>
constexpr bool condition = true;

template <>
constexpr bool condition<int> = false;

template <class... Ts>
struct type_vector {
    template <class... Ts2>
    type_vector<Ts..., Ts2...> operator+(type_vector<Ts2...>);
};

template <class... Ts,
          class Predicate>
auto copy_if(type_vector<Ts...>, Predicate p)
{
  return decltype(
      (type_vector<>{} + ... + 
          std::conditional_t<decltype(p(std::declval<Ts>())){}, 
                             type_vector<Ts>,
                             type_vector<>>{})){};
};

int main() {
    auto predicate = [](auto x){ return std::integral_constant<bool, condition<decltype(x)>>{};};
    std::cout << typeid(decltype(copy_if(type_vector<int, float, double>{}, predicate))).name() << std::endl;
}

[live demo]

关于c++ - 模板变量是否可以用作模板参数(类似于类模板)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43776007/

相关文章:

c++ - 使用两个模板参数调用函数

C++ 模板 vector 操作重载

java - 数组不会打印出其中的所有乘法,只打印一个

parameters - Inno Setup 中的/SL5、/SPAWNWND、/NOTIFYWND 和/DEBUGWND 参数是什么意思?

java - insert 语句参数太少

c# - C "FILE *f;"的 C# 是什么?

c++ - std::type_info::hash_code() 的唯一性和 "should"的含义

c++ - 是否可以让模板函数使用转换或推导指南来推导模板参数的类型?

c++ - 为什么在调用成员函数时 std::reference_wrapper 不隐式转换为引用?

c++ - 如何使这个 boost::enable_if 代码编译(SFINAE)?