Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.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++_Casting_Overloading_Implicit Conversion - Fatal编程技术网

C++ 隐式转换为模板

C++ 隐式转换为模板,c++,casting,overloading,implicit-conversion,C++,Casting,Overloading,Implicit Conversion,下面的示例表明,从非模板类型到模板类型的隐式转换不会像只涉及非模板类型的转换那样无缝。有没有办法让它们发挥作用 例如: struct point; template<unsigned d> struct vec { vec() { } // ... }; template<> struct vec<2> { vec() { } vec(const point& p) { /* ... */ } // Conversion const

下面的示例表明,从非模板类型到模板类型的隐式转换不会像只涉及非模板类型的转换那样无缝。有没有办法让它们发挥作用

例如:

struct point;

template<unsigned d> struct vec {
  vec() { }
  // ...
};

template<> struct vec<2> {
  vec() { }
  vec(const point& p) { /* ... */ } // Conversion constructor
  // ...
};

struct point {
  operator vec<2>() { return vec<2>(/* ... */); } // Conversion operator
};

template<unsigned d> vec<d> foo(vec<d> a, vec<d> b) {
  return vec<d>(/* ... */);
}

template<unsigned d1, unsigned d2>
vec<d1 + d2> bar(vec<d1> a, vec<d2> b) {
  return vec<d1 + d2>(/* ... */);
}

int main(int argc, char** argv) {
  point p1, p2;
  vec<2> v2;
  vec<3> v3;
  foo(v2, p1);
  foo(p2, v2);
  foo(p1, p2);
  bar(v3, p1);
}
struct点;
模板结构向量{
vec(){}
// ...
};
模板结构向量{
vec(){}
vec(常数点&p){/*…*/}//转换构造函数
// ...
};
结构点{
运算符vec(){return vec(/*…*/);}//转换运算符
};
模板向量foo(向量a、向量b){
返回向量(/*…*/);
}
模板
向量条(向量a、向量b){
返回向量(/*…*/);
}
int main(int argc,字符**argv){
点p1,p2;
vec v2;
vec-v3;
foo(v2,p1);
foo(p2,v2);
foo(p1,p2);
bar(v3,p1);
}
有没有办法让此代码从
点自动转换为
向量机

我知道我可以重载
foo
bar
以允许
point
参数,使用显式转换将其委托给
vec
实现。但对所有参数组合执行此操作将变得单调乏味,尤其是对于具有许多此类参数的函数。所以我对那些必须为每个函数的每个参数组合复制代码的解决方案不感兴趣


转换构造函数和cast操作符似乎都不足以实现这一点。至少我的GCC4.7.1报告了
没有匹配的函数调用
,尽管它确实在通知中命名了所需的函数,声明
“点”不是从“vec”派生出来的

,没有直接的方法获得从
向量
,因为在函数调用
foo(v1,p1)时
被处理,一个函数
foo
,它需要一个
vec
作为第二个参数,但它还不存在。它只是一个函数模板,为了将其实例化为一个
foo(const-vec&,const-vec&)
,必须给出具有这些确切参数类型的函数调用

为了使代码正常工作,编译器必须猜测如何实例化模板参数,以及要转换为的
参数的类型。这在一般情况下太多了(尽管在您的特定代码中它看起来很简单,因为没有其他可能的方法来解释程序员的意图)

为了解决这个问题,我唯一能想到的就是创建高度模板化的转换函数:

template <typename T>
struct make_vec
{ };

template <unsigned d>
struct make_vec<vec<d>>
{
  static constexpr unsigned dim = d;
  using type = vec<dim>;

  static const type &from(const type &v)
  { return v; }
};

template <>
struct make_vec<point>
{
  static constexpr unsigned dim = 2;
  using type = vec<dim>;

  static type from(const point &p)
  { return type(p); }
};

template <typename T>
typename make_vec<typename std::decay<T>::type>::type make_vec_from(T&& arg)
{ return make_vec<typename std::decay<T>::type>::from(std::forward<T>(arg)); }
bar
的情况下,您还需要一种计算返回类型的方法,即
vec
。为此,需要一个总和计算器,它也是模板化的:

template <typename... Ts>
struct dsum {
  static constexpr unsigned value = 0;
};

template <typename T, typename... Ts>
struct dsum<T,Ts...> {
  static constexpr unsigned value = make_vec<typename std::decay<T>::type>::dim + dsum<Ts...>::value;
};
模板
结构dsum{
静态constexpr无符号值=0;
};
模板
结构dsum{
static constexpr unsigned value=make_vec::dim+dsum::value;
};
然后,
bar()
的返回类型是
vec

下面是一个完全有效的示例:


不是很简单,但是如果你真的有很多不同的参数组合,那么这可能是值得的。

哪一行给出了这个错误?此外,未签名< /C> >不是C++类型。@杰姆斯:对于函数调用的行,报告了错误,尽管通知也提到了其他的行。请随意复制和编译上面的代码,因为它是自包含的。第三节的名字是代码> >未签名的<代码>,为什么这不是C++类型,与C共享?否,它声明<代码>未签名char <代码>,<代码>无符号短INT/COD>,<代码>未签名int < /COD>,<代码>未签名长INT//COD>,和<代码>未签名长long int /CONT>作为无符号整数类型。但是我离题。理论上,仅提供转换运算符就足够了。您在
vec
point
之间有循环引用,这可能会导致编译器感到困惑。我唯一可以强制它工作的变量是调用
foo(v2,p1)
。顺便说一句,没有必要将
操作符vec()
添加到
@MvG,我已经修改了“完整工作示例”。我的
bar
实现在第一个版本中是错误的。
template <typename... Ts>
struct dsum {
  static constexpr unsigned value = 0;
};

template <typename T, typename... Ts>
struct dsum<T,Ts...> {
  static constexpr unsigned value = make_vec<typename std::decay<T>::type>::dim + dsum<Ts...>::value;
};