【问题标题】:C++ Template argument changes Reference to PointerC++ 模板参数更改对指针的引用
【发布时间】:2011-03-15 18:25:24
【问题描述】:

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

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

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

SpecType 是对指针的引用(例如const char *&amp;)时,NonType 的行为就好像它是实际专用参数的地址,而不是引用。 更令人惊讶的是,如果我将NonType 明确转换为SpecType,一切都会按预期进行!

IBM 说了一些关于转换为数组和函数指针的事情,但我不明白这与我的疑问有关。

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

当然可以改成:

template<
    typename SpecType,
    SpecType &NonType >

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


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

#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"

【问题讨论】:

  • @Ben Voigt:g++ (GCC) 4.4.5 20101112 (Red Hat 4.4.5-2) 和 g++ (GCC) 4.3.2 20081105 (Red Hat 4.3.2-7)。跨度>

标签: c++ templates pointers


【解决方案1】:

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

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 的编译器是另一个给出与此非常相似的信息的编译器。

g++ 对其进行了编译(我认为是错误的)并给出了类似于您报告的输出。

【讨论】:

  • "$ g++ -Wall nontype_mutant.cpp -o nontype_mutant" 没有给我任何错误。我从自己的帖子中重新复制、重新编译并重新运行示例,以确保我没有做错任何事情。您可以安全地评论第 44 行,相关问题仍然存在。请在我的帖子中注意问题出在像指针一样的引用中,而不是间接编译错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 2016-01-11
相关资源
最近更新 更多