C++:如何防止模板专门化指针?

j4x*_*j4x 7 c++ templates pointers

我开始道歉,如果我是愚蠢的,如果它是如此明显,找不到答案.

我已经看过几十页讨论指针参数的特定模板专业化.

但是,我希望能够防止模板专门化指针参数,但我无法弄清楚如何做到这一点.

template< class T >
void function( T arg )
{
  //...
}

int main( )
{
    int i = 42;

    function( i );    // Ok
    function( &i );   // Die bastart with a compiler error!
}
Run Code Online (Sandbox Code Playgroud)

可能吗?

谢谢.

Arm*_*yan 14

你可以声明专门化(在这种情况下,它在技术上只是一个重载),但没有定义它:)

template<typename T >
void function( T arg )
{
//...
}

template<typename T >
void function( T* arg ); //no definition

int main()
{
    int i = 42;
    function( i );    // Ok
    function( &i );   //ERROR
}
Run Code Online (Sandbox Code Playgroud)

  • @ArmenTsirunyan:不,这是[链接器错误](http://ideone.com/so8Gp).函数模板*specialization*就像任何其他函数一样(或多或少),并且不必在它所使用的相同转换单元中定义. (6认同)
  • @MikeSeymour:这甚至是一个特殊的话题吗?两个模板都是功能模板,功能模板没有部分专业化.在我看来,它是一个类似于14.8.3/4中的例子的过载. (5认同)
  • @daknøk:这是一个编译器错误,因为它是一个模板.模板的定义应该在同一个翻译单元(源文件)中.链接器对模板一无所知.编译器负责模板实例化,如果没有定义,它就无法完成 (4认同)
  • 此解决方案存在两个问题.第一个,它自己的解决方案是它触发链接器错误,而不是编译器错误.SFINAE将是获取编译器错误的方法.第二个问题不是解决方案,而是答案,术语不正确.你**不能**部分专门化模板功能.你正在做的是声明一个不同的基本模板函数,它将更好地重载指针. (4认同)

小智 7

在C++ 11中,您可以使用static_assert以下方式:

template<class T>
void func(T arg) {
  static_assert(!std::is_pointer<T>::value,
                "The argument to func must not be a pointer.");
  // Do something after the static_assert.
  // Now you are sure that T isn't a pointer.
}
Run Code Online (Sandbox Code Playgroud)

可以在Ideone上找到一个例子.

我推荐这个,因为当有人试图用指针调用你的函数时,它会给出更有用的错误消息(链接器错误在这种情况下可能非常混乱).此外,链接错误在链接发生之​​前不会显示.


Chr*_*ica 6

我自己就是一个模板元编程新秀,但我想

template<typename T>
void function(typename std::enable_if<!std::is_pointer<T>::value,T>::type arg)
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

应该工作,因为这个函数应该只存在非指针参数.当然,这需要C++ 11或至少TR1或boost的类型特征设施.