C++ 模板参数更改对指针的引用 [英] C++ Template argument changes Reference to Pointer

查看:62
本文介绍了C++ 模板参数更改对指针的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许我不知道如何搜索,但事实上我找不到任何人在谈论这个.

Maybe I didn't know how to search, but it's fact that I couldn't find anyone talking about this.

我有一个结构体,它有一个 非类型 参数,它依赖于一个 type 参数.

I have struct that has a non-type argument that depends on a type argument.

template<
    typename SpecType,
    SpecType NonType >
struct Struct
//...

SpecType 是对指针的引用(例如,const char *&)NonType 的行为就好像它是地址一样实际的专业论证,而不是参考.更令人惊讶的是,如果我将 NonType 显式转换为 SpecType,一切都按预期进行!

When SpecType is a reference to a pointer (const char *&, for example) NonType behaves as if it is the address of the actual specialized argument, and not a reference. More surprising is that if I explicitly cast NonType to SpecType, everything works as expected!

IBM 说了一些关于转换为数组和函数指针的内容,但我不明白这与我的怀疑有关.

IBM says something about conversion to pointer of arrays and functions, but I don't understand it as related to my doubt.

当我创建没有嵌入模板类型(S1S2)的结构时,同样的事情不会发生.

When I create structs that have no embedded template types (S1 and S2) the same thing does ot happen.

当然我可以改成:

template<
    typename SpecType,
    SpecType &NonType >

但它不会解释我所看到的.谁能给一个深刻的(或愚蠢的,如果这是我的愚蠢)解释?

but it won't explain what I see. Can anyone please give a deep (or dumb, if it is my stupidness) explanation?

下面的例子有点冗长,但看​​看它的输出我想我的问题会更清楚:

The following example is a bit extense, but looking at its output I think my problem will be more clear:

#include    <iostream>
#include    <typeinfo>

using namespace std;


void    f1( const char **p )
{
    cout << "---------------------------------------------" << endl;
    cout << "f1( const char **p ): p = \"" << p << "\"" << endl;
}

void    f1( const char *p )
{
    cout << "---------------------------------------------" << endl;
    cout << "f1( const char *p ): p = \"" << p << "\"" << endl;
}

void    f1( const int **p )
{
    cout << "---------------------------------------------" << endl;
    cout << "f1( const int **p ): p = \"" << p << "\"" << endl;
}

void    f1( const int *p )
{
    cout << "---------------------------------------------" << endl;
    cout << "f1( const int *p ): p = \"" << p << "\"" << endl;
}

template<
    typename SpecType,
    SpecType NonType >
struct Struct
{
    void    f( )
    {
        cout << "---------------------------------------------" << endl;
        cout << "SpecType is " << typeid( SpecType ).name( ) << endl;
        cout << "NonType is " << typeid( NonType ).name( ) << endl;
        cout << "NonType = \"" << NonType << "\"" << endl;
        cout << "( SpecType )NonType = \"" << ( SpecType )NonType << "\"" << endl;
        cout << "*NonType = \"" << *NonType << "\"" << endl;
        cout << "*NonType[ 0 ] = \"" << **NonType << "\"" << endl;

        f1( NonType );
    }
};

template< const char *&P >
struct  S1
{
    void    f( )
    {
        cout << "---------------------------------------------" << endl;
        cout << "&P = \"" << &P << "\"" << endl;
        cout << "P = \"" << P << "\"" << endl;
        cout << "*P = \"" << *P << "\"" << endl;

        f1( P );
    }
};

template< const char **P >
struct  S2
{
    void    f( )
    {
        cout << "---------------------------------------------" << endl;
        cout << "P = \"" << P << "\"" << endl;
        cout << "*P = \"" << *P << "\"" << endl;
        cout << "*P[ 0 ] = \"" << **P << "\"" << endl;

        f1( P );
    }
};

const char * const_pname    = "name";

const int   pint[]  = { 42, 51 };
const int   *const_pint = pint;

int main( )
{
    cout << "=============================================" << endl;
    cout << "const_pname = " << const_pname << endl;
    cout << "@const_pname = 0x" << hex << ( unsigned long )const_pname << dec << endl;
    cout << "&const_pname = 0x" << hex << ( unsigned long )&const_pname << dec << endl;

    cout << "=============================================" << endl;
    cout << "Struct< const char *&, const_pname >   constpTtname" << endl;
    Struct< const char *&, const_pname >    constpTtname;
    constpTtname.f( );

    cout << "=============================================" << endl;
    cout << "Struct< const int *&, const_pint > constpTtint" << endl;
    Struct< const int *&, const_pint >  constpTtint;
    constpTtint.f( );

    cout << "=============================================" << endl;
    cout << "S1< const_pname >  s1" << endl;
    S1< const_pname >   s1;
    s1.f( );

    cout << "=============================================" << endl;
    cout << "S2< &const_pname > s2" << endl;
    S2< &const_pname >  s2;
    s2.f( );

    return  0;
}

输出为:

$ ./nontype_mutant
=============================================
const_pname = name
@const_pname = x401624                                                                   
&const_pname = 0x601e18                                                                   
=============================================                                             
Struct< const char *&, const_pname >    constpTtname                                      
---------------------------------------------                                             
SpecType is PKc                                                                           
NonType is PKc                                                                            
NonType = "$@"                                                                            
( SpecType )NonType = "name"                                                              
*NonType = "name"                                                                         
*NonType[ 0 ] = "n"                                                                       
---------------------------------------------                                             
f1( const char *p ): p = "$@"                                                             
=============================================                                             
Struct< const int *&, const_pint >      constpTtint                                       
---------------------------------------------                                             
SpecType is PKi                                                                           
NonType is PKi                                                                            
NonType = "0x601e20"                                                                      
( SpecType )NonType = "0x4017a8"                                                          
*NonType = "0x4017a8"                                                                     
*NonType[ 0 ] = "42"                                                                      
---------------------------------------------                                             
f1( const int *p ): p = "0x601e20"                                                        
=============================================                                             
S1< const_pname >       s1
---------------------------------------------
&P = "0x601e18"
P = "name"
*P = "n"
---------------------------------------------
f1( const char *p ): p = "name"
=============================================
S2< &const_pname >      s2
---------------------------------------------
P = "0x601e18"
*P = "name"
*P[ 0 ] = "n"
---------------------------------------------
f1( const char **p ): p = "0x601e18"

推荐答案

我尝试使用三个编译器编译您的代码,其中两个具有非常相似的行为,给出以下消息(大约):

I've tried to compile your code using three compilers and two of them have very similar behavior giving the following message (approximately):

test.cpp:44:41: error: indirection requires pointer operand ('int' invalid)
        cout << "*NonType[ 0 ] = \"" << **NonType << "\"" << endl;
                                        ^~~~~~~~~
test.cpp:93:18: note: in instantiation of member function 'Struct<const char *&, const_pname>::f' requested here
    constpTtname.f( );
                 ^
test.cpp:44:41: error: indirection requires pointer operand ('int' invalid)
        cout << "*NonType[ 0 ] = \"" << **NonType << "\"" << endl;
                                        ^~~~~~~~~
test.cpp:98:17: note: in instantiation of member function 'Struct<const int *&, const_pint>::f' requested here
    constpTtint.f( );
                ^
2 errors generated.

错误信息对我来说似乎是正确且不言自明的.这是使用clang的结果.Comeau 基于 EDG 的编译器是另一个给出与此非常相似的消息的编译器.

The error message seems correct and self evident to me. This was the result of using clang. Comeau's EDG based compiler was the other one to give a message very similar to this.

g++ 编译它(我认为是错误的)并给出与您报告的类似的输出.

g++ compiled it (I believe incorrectly) and gave an output similar to that you report.

这篇关于C++ 模板参数更改对指针的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆