简体   繁体   English

C ++模板参数更改引用指针

[英]C++ Template argument changes Reference to Pointer

Maybe I didn't know how to search, but it's fact that I couldn't find anyone talking about this. 也许我不知道如何搜索,但事实上我找不到任何人在谈论这个。

I have struct that has a non-type argument that depends on a type argument. 我有一个struct,它有一个取决于类型参数的 类型参数。

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

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. SpecType是对指针的引用时(例如, const char *& ), NonType行为就好像它是实际专用参数的地址,而不是引用。 More surprising is that if I explicitly cast NonType to SpecType , everything works as expected! 更令人惊讶的是,如果我将NonType显式地NonTypeSpecType ,一切都按预期工作!

IBM says something about conversion to pointer of arrays and functions, but I don't understand it as related to my doubt. IBM谈到了转换为数组和函数指针的问题,但我不理解它与我的疑问有关。

When I create structs that have no embedded template types ( S1 and S2 ) the same thing does ot happen. 当我创建没有嵌入模板类型( S1S2 )的结构时,同样的事情就会发生。

Of course I can change it to: 当然我可以改为:

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;
}

The output is: 输出是:

$ ./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.

The error message seems correct and self evident to me. 错误信息对我来说似乎是正确和明显的。 This was the result of using clang. 这是使用clang的结果。 Comeau's EDG based compiler was the other one to give a message very similar to this. Comeau的基于EDG的编译器是另一个给出与此非常相似的消息。

g++ compiled it (I believe incorrectly) and gave an output similar to that you report. g ++编译它(我认为不正确)并给出类似于你报告的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM