一类嵌套类不能用作模板函数typename

时间:2018-04-06 15:10:33

标签: c++

对于嵌套类,我想使用一类嵌套类作为模板类型名称,请参阅下面的代码:

#include <stdio.h>
#include <stdint.h>

struct H264 {
    struct NAL_UNIT {
        uint8_t nal_ref_idc;
        uint8_t nal_unit_type;
    };
};

struct H265 {
    struct NAL_UNIT {
        uint8_t nal_unit_type;
        uint8_t nuh_layer_id;
        uint8_t nuh_temporal_id_plus1;
    };
};

template <class T> void PrintNALUnitType(T::NAL_UNIT& nal_unit) {
    printf("nal_unit_type: %d.\n", nal_unit.nal_unit_type);
}

int main() {
    H264::NAL_UNIT h264_nu;
    h264_nu.nal_ref_idc = 2;
    h264_nu.nal_unit_type = 5;

    H265::NAL_UNIT h265_nu;
    h265_nu.nal_unit_type = 35;
    h265_nu.nuh_layer_id = 0;
    h265_nu.nuh_temporal_id_plus1 = 1;

    PrintNALUnitType(h264_nu);
    return 0;
}

然而,它无法在gcc中编译,

namespace.cpp:22:26: error: variable or field ‘PrintNALUnitType’ declared void
 void PrintNALUnitType(T::NAL_UNIT& nal_unit)
                          ^~~~~~~~
namespace.cpp:22:36: error: ‘nal_unit’ was not declared in this scope
 void PrintNALUnitType(T::NAL_UNIT& nal_unit)
                                    ^~~~~~~~
namespace.cpp:22:36: note: suggested alternative: ‘__unix’
 void PrintNALUnitType(T::NAL_UNIT& nal_unit)
                                    ^~~~~~~~
                                    __unix
namespace.cpp: In function ‘int main()’:
namespace.cpp:38:5: error: ‘PrintNALUnitType’ was not declared in this scope
     PrintNALUnitType(h264_nu);
     ^~~~~~~~~~~~~~~~

我知道可以通过改变

来修复它
template <class T>
void PrintNALUnitType(T::NAL_UNIT& nal_unit)

template <class T>
void PrintNALUnitType(T& nal_unit)

但我只是想知道为什么它打破了c ++规范,有人可以给出一些提示吗?

2 个答案:

答案 0 :(得分:2)

实际上,对于函数调用中的模板参数推导,不能从嵌套类名推导出包含类名。在您的模板功能中:

04-07 00:03:19.528 18645-18645/com.example.android.justjava E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.android.justjava, PID: 18645
    java.lang.RuntimeException: Unable to get provider com.android.tools.ir.server.InstantRunContentProvider: java.lang.ClassNotFoundException: Didn't find class "com.android.tools.ir.server.InstantRunContentProvider" on path: DexPathList[[zip file "/data/app/com.example.android.justjava-36.apk"],nativeLibraryDirectories=[/data/app-lib/com.example.android.justjava-36, /vendor/lib, /system/lib]]
        at android.app.ActivityThread.installProvider(ActivityThread.java:5355)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:4930)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4870)
        at android.app.ActivityThread.access$1600(ActivityThread.java:174)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1385)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5752)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.android.tools.ir.server.InstantRunContentProvider" on path: DexPathList[[zip file "/data/app/com.example.android.justjava-36.apk"],nativeLibraryDirectories=[/data/app-lib/com.example.android.justjava-36, /vendor/lib, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
        at android.app.ActivityThread.installProvider(ActivityThread.java:5340)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:4930) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4870) 
        at android.app.ActivityThread.access$1600(ActivityThread.java:174) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1385) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:146) 
        at android.app.ActivityThread.main(ActivityThread.java:5752) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107) 
        at dalvik.system.NativeStart.main(Native Method) 

template <class T> void PrintNALUnitType(typename T::NAL_UNIT& nal_unit) { printf("nal_unit_type: %d.\n", nal_unit.nal_unit_type); } 中调用函数时,无法从参数类型推导出模板参数T.

[temp.deduct.type]/8列出模板函数参数类型必须可以扣除的可能形式:

  

如果P和A具有以下形式之一,则可以推导出模板类型参数T,模板模板参数TT或模板非类型参数i:

     

Ť

     

cv-list T

     

T *

     

T&安培;

     

T&安培;&安培;

     

T [整数常数]

     

template-name(其中template-name指的是类模板)

     

型(T)

     

T()

     

T(T)

     

T type :: *

     

输入T :: *

     

T T :: *

     

T(type :: *)()

     

type(T :: *)()

     

type(type :: *)(T)

     

type(T :: *)(T)

     

T(type :: *)(T)

     

T(T :: *)()

     

T(T :: *)(T)

     

键入[I]

     

template-name(其中template-name指的是类模板)

     

TT

     

TT

     

TT&LT;&GT;

     

其中(T)表示参数类型列表([dcl.fct]),其中至少一个参数类型包含T,而()表示参数类型列表,其中没有参数类型包含T. ,表示模板参数列表,其中至少一个参数包含T,表示模板参数列表,其中至少一个参数包含i和&lt;&gt;表示模板参数列表,其中没有参数包含T或i。

答案 1 :(得分:1)

您可以使用以下内容:

template <class X>
void PrintNALUnitType(typename X::NAL_UNIT& nal_unit) {
    printf("nal_unit_type: %d.\n", nal_unit.nal_unit_type);
}

int main() {  
.
.
    PrintNALUnitType<H265>(h265_nu);
}