具有可变数量的特定类型参数的 C++ 函数

C++ function with a viariable number of arguments of a certain type

我刚刚了解了 C++ 中的可变参数模板。我实现了,但我想知道,它能做到以下几点吗?

如果我想要一个参数数量可变的函数,我可以这样做:

template <typename... Ts>
f(Ts... args);

但是我失去了类型安全(我不知道参数的类型)。

如果我知道我的函数只需要 float 作为参数怎么办?我想在编译时确保每个参数都是我想要的类型。

所以这些是我的问题:

Ps:是的,我可以使用 std::vectorstd::array 作为参数,但这不是重点。另外,我想保留漂亮的 Vector(2.0, 1.0, 0.0) 语法,而不是使用大括号。

如果编译器支持C++ 20那么你可以这样写

#include <type_traits>

template <typename T, uint16_t dimension>
class Vector
{
public:
    template <typename... Ts>
    Vector( Ts &&... args ) requires ( sizeof...( args ) == dimension ) && std::conjunction_v<std::is_same<T, std::decay_t<Ts>>...>
    {
    }
};

//...

Vector<float, 5> v( 1.1f, 2.2f, 3.3f, 4.4f, 5.5f );

或者如@HolyBlackCat在评论中所写,您也可以写

template <typename T, uint16_t dimension>
class Vector
{
public:
    template <typename... Ts>
    Vector( std::same_as<T> auto ...args ) requires( sizeof...( args ) == dimension )
    {
    }
};
template <typename T, uint16_t dimension>
class MyVector
{
  public:
    template <typename... Ts>
    MyVector(Ts... args)
    {
        static_assert(sizeof...(args) == dimension);
        static_assert((std::is_same<T,Ts>::value && ...) );
    }
};

也可以使用C++17提供的一元右折叠表达式 https://en.cppreference.com/w/cpp/language/fold

这基本上是

std::is_same<T,Ts_1>::value && ( std::is_same<T,Ts_2>::value && ... std::is_same<T,Ts_n>::value ) ...)

并且在参数包 Ts 为空时也有效。引自参考 link:

" Logical AND (&&). The value for the empty pack is true"

对于固定矢量的情况,如您的情况,有一个替代方案 std::index sequence:

// helper for folding
template <typename T, std::size_t /*ignored*/>
using always_t = T;

template <typename T, typename Seq>
class VectorImpl;

template <typename T, std::size_t... Is>
class VectorImpl<T, std::index_sequence<Is...>>
{
public:
    VectorImpl(always_t<T, Is>... args); // equivalent to VectorImpl(T arg1, T arg2, ..)
    // ...
};

template <typename T, std::size_t N>
using Vector = VectorImpl<T, std::make_index_sequence<N>>;