Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何为创建静态和动态大小向量提供公共接口?_C++_C++11_Templates_C++14_Sfinae - Fatal编程技术网

C++ 如何为创建静态和动态大小向量提供公共接口?

C++ 如何为创建静态和动态大小向量提供公共接口?,c++,c++11,templates,c++14,sfinae,C++,C++11,Templates,C++14,Sfinae,我目前有很多代码可以处理动态大小向量(例如std::vector,Eigen::VectorXd,…),我希望它也可以处理静态大小向量(例如std::array,Eigen::Vector3d,…)。我的代码是针对TVector模板化的,它假定TVector只有size和操作符[]。但最大的问题是建筑 当涉及到静态和动态向量的构造时,没有共同点。我决定用以下假设函数替换对TVector构造函数的所有调用: template <typename TVector> TVector cre

我目前有很多代码可以处理动态大小向量(例如
std::vector
Eigen::VectorXd
,…),我希望它也可以处理静态大小向量(例如
std::array
Eigen::Vector3d
,…)。我的代码是针对
TVector
模板化的,它假定
TVector
只有
size
操作符[]
。但最大的问题是建筑

当涉及到静态和动态向量的构造时,没有共同点。我决定用以下假设函数替换对
TVector
构造函数的所有调用:

template <typename TVector>
TVector createVector(std::size_t sizeAtInitialization)
{
    if (TVector has constructor taking an integral type)
        return TVector(sizeAtInitialization);
    else
        return TVector(); // sizeAtInitialization ignored
}
模板
TVector createVector(标准::大小\u t大小初始化)
{
if(TVector的构造函数采用整型)
返回TVector(大小初始化);
其他的
返回TVector();//忽略了sizeAtInitialization
}
这样,对
createVector
的一般调用将变成
createVector(3)
createVector(3)

这对我没有帮助,因为这两种向量类型都是默认可构造的

然而,我甚至不确定这样的事情是否可能发生


我研究了静态if成员函数检测。这一切看起来都非常复杂,因为
static\u if
使用lambda,它必须返回到中间结果,必须已经构造好,我不确定它会导致任何结果。

你可以使用
std::is\u constructible
和一点sfinae和
std::enable\u if

using namespace std;

template <class T>
using IntegerConstructible =
    typename enable_if<is_constructible<T, int>::value, T>::type;

template <class T>
using NotIntegerConstructible =
    typename enable_if<!is_constructible<T, int>::value, T>::type;

template<class T>
auto createVector(int size)
  -> IntegerConstructible<T> {
  return {size};
}

template<class T>
auto createVector(int size)
  -> NotIntegerConstructible<T>{
  return {};
}

int main(){
  auto x = createVector<std::vector<int>>(3);
  auto y = createVector<std::array<int,3>>(3);
  return 0;
}
使用名称空间std;
模板
使用integerconstructable=
typename enable_if::type;
模板
使用NotIntegerConstructable=
typename enable_if::value,T>::type;
模板
自动创建向量(整数大小)
->整数可构造{
返回{size};
}
模板
自动创建向量(整数大小)
->非整数可构造{
返回{};
}
int main(){
auto x=createVector(3);
自动y=createVector(3);
返回0;
}
IntegerConstructible
NotIntegerConstructible
是别名模板,只要可以(或不能)构造模板参数,就可以定义这些模板。定义时
IntegerConstructible=T

因此,两个
createVector
函数中只有一个具有有效的返回类型,另一个不能调用。这允许编译器选择正确的重载。

我喜欢SFINAE(+1代表Tim),但我认为标记分发对于此类问题更为清晰

#include <array>
#include <vector>
#include <iostream>
#include <type_traits>

template <typename T>
T cVH (int size, std::true_type const &)
 { std::cout << "with size" << std::endl; return { size }; }

template <typename T>
T cVH (int, std::false_type const &)
 { std::cout << "without size" << std::endl; return { }; }

template <typename T>
T createVector (int size)
 { return cVH<T>(size, typename std::is_constructible<T, int>::type{}); }

int main()
 {
  auto x = createVector<std::vector<int>>(3);   // print "with size"
  auto y = createVector<std::array<int,3>>(3);  // print "without size"
 }

您可以创建一个类型trait,并为使用的每个类型定义它。然后,可以使用SFINAE评估该特性,以选择静态或动态初始化函数。@NathanOliver与为每种类型专门化
createVector
相比,这有什么好处吗?“只是好奇。”鲁道夫·邦杜利斯说,“我认为这样传播比较容易。现在,使用函数所需要做的就是添加适当的类型特征,而不必添加自己的函数专门化。但是作为
Eigen::VectorXd
Eigen::Vector3d
基础的
Eigen::Matrix
模板类有一个带int参数的构造函数。
#include <array>
#include <vector>
#include <iostream>
#include <type_traits>

template <typename>
struct withSize;

template <typename T>
struct withSize<std::vector<T>>
 { using type = std::true_type; };

template <typename T, std::size_t N>
struct withSize<std::array<T, N>>
 { using type = std::false_type; };

// others specializations of withSize for Eigen::Vector3d, Eigen::Matrix, etc.

template <typename T>
T cVH (int size, std::true_type const &)
 { std::cout << "with size" << std::endl; return { size }; }

template <typename T>
T cVH (int, std::false_type const &)
 { std::cout << "without size" << std::endl; return { }; }

template <typename T>
T createVector (int size)
 { return cVH<T>(size, typename withSize<T>::type{}); }

int main()
 {
  auto x = createVector<std::vector<int>>(3);   // print "with size"
  auto y = createVector<std::array<int,3>>(3);  // print "without size"
 }