在C++中跳过多变量模板/函数

在C++中跳过多变量模板/函数,c++,c++11,gcc,compilation,C++,C++11,Gcc,Compilation,免责声明-老实说,我不知道如何界定这个问题或提供适当的背景,如果有此问题经验的人能够建议我需要提供哪些额外信息来澄清背景,我将不胜感激。而且,如果我需要清理下面的代码部分以使其更清晰,我会在收到评论时这样做 但不管怎样,事情还是这样- 我试图使用可变模板,但每次我在公司代码库上编译代码时,编译器GCC4.8.4-C++11似乎跳过了所有可变代码部分- TestFactory.cpp TestFactory.cpp 调用文件- 当我编译这个GCC4.8.4时,对象文件TestFactory.o是空

免责声明-老实说,我不知道如何界定这个问题或提供适当的背景,如果有此问题经验的人能够建议我需要提供哪些额外信息来澄清背景,我将不胜感激。而且,如果我需要清理下面的代码部分以使其更清晰,我会在收到评论时这样做

但不管怎样,事情还是这样-

我试图使用可变模板,但每次我在公司代码库上编译代码时,编译器GCC4.8.4-C++11似乎跳过了所有可变代码部分-

TestFactory.cpp

TestFactory.cpp

调用文件-

当我编译这个GCC4.8.4时,对象文件TestFactory.o是空的。如果在代码库GCC4.4.6之外执行此操作,代码将被编译并输出-

[common]$ nm TestFactory.o | c++filt $1 | grep CreateTest
34:0000000000401d6a W NpBaseTest* TestFactory::CreateTest<unsigned short>(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short&&)
[common]$ nm TestFactory.o | c++filt $1 | grep RegisterTest
35:0000000000401d40 W void TestFactory::RegisterTest<unsigned short>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, NpBaseTest* (*)(unsigned short))

模板仅在使用时实例化。将定义放在实现中而不在该文件中使用它们将不会导致实例化。然后,当您尝试在其他地方使用它时,它将发现没有可实例化的实现,因为它位于当前翻译单元看不到的实现文件中。您应该将实现保留在标题中

如果您有一个NpBaseTest的定义,并且您移动了头TestFactory.h中的所有代码,那么您的示例工作得很好。下面是一个如何使用示例中的代码的示例。请注意,模板的编写方式只接受指向返回NpBaseTest*的函数的指针

我已经明确地为Clary编写了模板参数。在您的例子中,编译器将能够推断出这些参数,并且示例将大大简化。您只需调用模板化方法而不需要任何参数,它们将从参数中推导出来

// main.cpp
#include "TestFactory.h"
#include <iostream>

NpBaseTest* test_callback(int x, int y)
{
    std::cout << "Called test_callback(" << x << ", " << y << ")\n";
    return nullptr;
}

int main()
{
    // This instantiates TestFactory::RegisterTest<int, int>
    TestFactory::RegisterTest("my test", &test_callback);

    // This instantiates TestFactory::CreateTest<int, int>
    NpBaseTest * result = TestFactory::CreateTest("my test", 5, 10);

    return 0;
}

就这样。如果尝试此示例,您将看到TestFactory::RegisterTest和TestFactory::CreateTest的符号现在已生成。

使用c标记是有原因的还是您觉得它美观?模板仅在使用时实例化。将定义放在实现中而不在该文件中使用它们将不会导致实例化。然后,当您尝试在其他地方使用它时,它将发现没有可实例化的实现,因为它位于当前翻译单元看不到的实现文件中。您应该将实现保留在标题中@弗朗索瓦·桑德里奥:我将试一试,并提供更新!谢谢你的链接@既然这是一个可变的模板,我该如何实例化它呢?我可以接受变量参数和类型。如果我指定了类型,我是否违背了使用可变模板的目的?@nitimalh我假设您打算在某个时候使用可变模板函数,这样您就知道需要什么类型,即使这些类型本身就是模板参数。这是您将实例化的点。只有在使用模板时,才会根据设计进行实例化。我觉得你担心这些符号没有定义。不用担心,只要你的实现是可访问的,只要它在你的头中,它们就会在你实际使用模板的时候被定义。嘿,谢谢你的详细回答,这样肯定行得通!但有一件事让我感到困惑,那就是我在任何对象文件中都找不到RegisterTest或CreateTest符号??!我检查了.o文件中的调用文件main.c和TestFactory.o?有什么想法吗?@nitimalh我不是gcc专家,我无法自信地回答你为什么找不到符号。这可能是另一个问题的理由。
    void np_test_mgr_print()
    {
        const char *s = "cavpkotest";
        std::string str(s);
        TestFactory::RegisterTest(str.c_str(), &CavPkoTest::create);
        NpBaseTest *o1{TestFactory::CreateTest<uint16_t>(str.c_str(), 1)};
        /* Irrelevant code section */
        NpTestMgr::get_instance().insert(o1);
        NpTestMgr::get_instance().submit();
    }
}
[common]$ nm TestFactory.o | c++filt $1 | grep CreateTest
34:0000000000401d6a W NpBaseTest* TestFactory::CreateTest<unsigned short>(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned short&&)
[common]$ nm TestFactory.o | c++filt $1 | grep RegisterTest
35:0000000000401d40 W void TestFactory::RegisterTest<unsigned short>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, NpBaseTest* (*)(unsigned short))
// main.cpp
#include "TestFactory.h"
#include <iostream>

NpBaseTest* test_callback(int x, int y)
{
    std::cout << "Called test_callback(" << x << ", " << y << ")\n";
    return nullptr;
}

int main()
{
    // This instantiates TestFactory::RegisterTest<int, int>
    TestFactory::RegisterTest<int, int>("my test", &test_callback);

    // This instantiates TestFactory::CreateTest<int, int>
    NpBaseTest * result = TestFactory::CreateTest<int, int>("my test", 5, 10);

    return 0;
}
// main.cpp
#include "TestFactory.h"
#include <iostream>

NpBaseTest* test_callback(int x, int y)
{
    std::cout << "Called test_callback(" << x << ", " << y << ")\n";
    return nullptr;
}

int main()
{
    // This instantiates TestFactory::RegisterTest<int, int>
    TestFactory::RegisterTest("my test", &test_callback);

    // This instantiates TestFactory::CreateTest<int, int>
    NpBaseTest * result = TestFactory::CreateTest("my test", 5, 10);

    return 0;
}