简体   繁体   English

在 C++ 中是否可以有一个“通用”模板参数,它可以是非类型模板参数或类型?

[英]Is it possible to have a "generic" template parameter in C++, that can be either a non-type template parameter or a type?

In C++, it's possible to use a type as a template parameter, eg:在 C++ 中,可以使用类型作为模板参数,例如:

template <typename T>
void MyFn();

It's also possible to use a non-type as a template parameter in some cases, eg:在某些情况下,也可以使用非类型作为模板参数,例如:

template <int64_t T>
void MyFn2();

My question is whether it's possible to have a "generic" template parameter that can be both?我的问题是是否有可能有一个“通用”模板参数可以是两者? Like:喜欢:

template <TypenameOrint64_t T>
void MyFn3();

such that both MyFn3<42> and MyFn3<double> would be acceptable.这样MyFn3<42>MyFn3<double>都是可以接受的。

An example of how I might use this:我如何使用它的一个例子:

template <typename ValType, ValType Head, ValType ...Tail>
struct ListS{

  template <typename OutType, template <ValType ArgType> class Fn>
  using MapHead = ListS<OutType, Fn<Head>::val, Tail...>;
};

template<int64_t N>
struct SquareS{
  static constexpr const int64_t val = N * N;
};

using Sqrd = ListS<int64_t, 3, 4>::MapHead<int64_t, SquareS>;

static_assert(std::is_same<Sqrd, ListS<int64_t, 9, 4>>::value, "Values don't match");

The above is a very rough sketch of a compile-time list of values along with a single compile-time "function" on it.上面是一个非常粗略的编译时值列表以及一个编译时“函数”。 Would it be possible to make something like that also support lists of types, not just lists of non-type template param compatible values, without just duplicating all the code?是否有可能使类似的东西也支持类型列表,而不仅仅是非类型模板参数兼容值的列表,而不仅仅是复制所有代码?

Is it possible to have a “generic” template parameter in C++, that can be either a non-type template parameter or a type?在 C++ 中是否可以有一个“通用”模板参数,它可以是非类型模板参数或类型?

Short answer: no.简短的回答:没有。

Long answer.长答案。

No. The best I can imagine to mix types and values is wrap values in types, using std::integral_constant , by example.不。我能想象的最好的混合类型和值是将值包装在类型中,例如使用std::integral_constant

So, your desired code, could be written (C++17) almost as follows所以,你想要的代码,几乎可以写成(C++17)如下

#include <utility>

template <typename ...>
struct ListS;

template <typename ValType, ValType Head, ValType ...Tail>
struct ListS<std::integral_constant<ValType, Head>,
             std::integral_constant<ValType, Tail>...>
 {
   template <template <auto> class Fn, typename OutType = ValType>
   using MapHead = ListS<std::integral_constant<OutType, Fn<Head>::value>,
                         std::integral_constant<OutType, Tail>...>;
 };

template <auto N>
struct SquareS : public std::integral_constant<decltype(N), N*N>
 { };

int main ()
 {   
   using T1 = ListS<std::integral_constant<long long, 3ll>,
                    std::integral_constant<long long, 4ll>>;
   using T2 = T1::MapHead<SquareS>;
   using T3 = ListS<std::integral_constant<long long, 9ll>,
                    std::integral_constant<long long, 4ll>>;

   static_assert( std::is_same_v<T2, T3> );
 } 

Pre C++17 you can't use auto for the type of the template values so you should make some simple corrections.在 C++17 之前,您不能将auto用于模板值的类型,因此您应该进行一些简单的更正。

You could use function overloading and the auto type deduction that came with C++17 to accomplish something similar.您可以使用C++17附带的函数重载和auto类型推导来完成类似的工作。

template<typename myType>
auto myFn3(myType value){
    return value;
}

template<auto value> //takes any non-type parameter
auto myFn3(){
    return value;
}

int main(){
     auto test1_normal = myFn3(3);
     auto test1_cast = myFn3<double>(3); //able to perform a cast
     auto test1_auto = myFn3<3>();
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM