我有很多代码目前适用于动态尺寸向量(例如std::vector
,Eigen::VectorXd
,...),我希望它能够工作使用静态大小向量(例如std::array
,Eigen::Vector3d
,...)。我的代码在TVector
方面被模板化,假设TVector
只有size
和operator[]
。但最大的问题是建设。
在构建静态和动态向量时,没有共同点。我决定用以下假设函数替换对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
}
这样对[{1}}的通用调用将变为createVector<TVector>
或createVector<std::vector<double>>(3)
。
std::is_default_constructible在这里不会帮助我,因为两种矢量类型都是默认可构造的。
然而,我不确定这样的事情是否可能。
我研究了静态if here和成员函数检测 here。这一切看起来都非常复杂,因为createVector<std::array<double, 3>>(3)
使用的lambda必须返回到必须已经构造的中间结果,我不确定它是否会导致任何结果。
答案 0 :(得分:2)
您可以将std::is_constructible
与一些sfinae和std::enable_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;
}
IntegerConstructible
和NotIntegerConstructible
是别名模板,只要模板参数可以(或不能构造),就可以定义它们。定义时
IntegerConstructible<T> = T
。
因此,只有两个createVector
函数中只有一个具有有效的返回类型,另一个函数无法调用。这允许编译器选择正确的重载。
答案 1 :(得分:1)
我喜欢SFINAE(Tim为+1),但我认为此类问题的标签调度更清晰
#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"
}
---编辑---
如果没有可以为所有眼睛选择正确值的类型特征,您可以自己创建一个(struct withSize
)跟随
#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"
}