模板变量是否可以用作模板参数(类似于类模板)?
问题描述:
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++ filt的输出:
type_vector<float, double>
编辑:
采用人工标记派遣参数类型时,有情况可能被视为如同繁琐。如果你想避免它,还有另一种方法。这实际上是一个呼吁避免拉姆达的operator()
模板,它只是进行实例化评估结果类型(这应该是等同的任何std::true_type
或std::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;
}
你定义type_vector? –
@RichardHodges是的,'type_vector'被定义,与'operator +'相同,用于连接两个'type_vector' – Rumburak
我不太了解C++ 17,但在我看来,'template auto'没有任何意义,因为汽车只能是一个班级。例如没有'template int'的概念, –