首页 > 解决方案 > c++ 中嵌套模板函数的 const 限定符

问题描述

我想要一个模板函数barconst限定符调用模板函数foo 。

我有两个用于函数foobar的模板及其实例化。这是foo.cpp

#include "foo.h"
#include <iostream>

template <class T>
void foo(const T x){
    std::cout<<x[0]<<std::endl;
};
// instantiation here, in order to avoid implementation in header
template void foo<const int*>(const int*);

foo.h

template <class T>
void foo(T x);

bar.cpp

#include "bar.h"
#include "foo.h"
#include <iostream>

template <class T>
void bar(T x){
    foo<const T>(x);
};
// instantiation here, in order to avoid implementation in header
template void bar<int*>(int*);

bar.h

template <class T>
void bar(T x);

最后,main.cpp

#include <iostream>
#include "bar.h"
#include "foo.h"
int main()
{
    int p[5];
    p[0]=17;
    foo(p);
    bar(p);
    return 0;
}

所有 .h 文件都包含 #ifndef/#define 标准语句。函数foo应该得到一个int的数组,而不是改变它,因此它有const限定符。我希望函数bar接收一个int数组并对其进行更改,而在某些时候它也应该调用函数foo。使用模板的原因是将来我想为不同类型的数据调用这些函数,例如double*std::vector< int >&等。

当我尝试编译时,出现以下错误:

undefined reference to `void foo<int* const>(int* const)'

好像它不能将int*转换为const int*。此外,它似乎将指向 const int 的指针替换为指向 int 的 const 指针。知道我该如何处理吗?

另一个观察:如果我删除foo.cppbar.cpp而是将所有内容合并到一个文件中,它会正常编译。

====================================

案件已解决

foo的实例化是为< const int* >完成的。正如人们注意到的那样,当在bar中调用foo时,const T被强制转换为T const == int * const,这与const int*不同。

为了将其转换为int const*,我在代码中添加了:

typedef typename std::remove_pointer<T>::type tmp_type; // tmp_type = int
foo<tmp_type const *>(x);

你需要 -std=c++11 来编译它。或者,正如 Davis Herring 建议的那样,您可以使用

foo<const std::remove_pointer_t<T>*>(x);

相反,但您需要为此使用 -std=c++14 。

该问题与头文件中模板的实现无关,除了明显观察到如果所有内容都在一个文件中则不需要这些。

另一种解决方案是对 foo 进行两个实例化:

template void foo<int const *>(int const *);
template void foo<int *>(int *);

其中第一个不允许您更改函数内指针的值,而第二个允许您仅在其中传递简单的int*

标签: c++templatesconstants

解决方案


如果Tint*const Tint *const,不是const int*。(毕竟,给定

typedef const T cT;
cT t1=/*…*/,t2=/*…*/;

t1=t2是禁止的,不是*t1=*t2。)

您可以使用const std::remove_pointer_t<T>*构造const int*from int*


推荐阅读