代码之家  ›  专栏  ›  技术社区  ›  bremen_matt

C++:在库中实例化多个模板

  •  2
  • bremen_matt  · 技术社区  · 7 年前

    我有一个类库,它的模板大小为:

    foo.hpp

    template <size_t N>
    struct Foo {
       void bar();
    };
    

    foo.cpp

    template <size_t N>
    void Foo<N>::bar() {
    ...
    };
    

    我希望编译后的版本安装到cpp文件中定义的特定大小列表中。在伪代码中,类似这样的

    食品.cpp

    template <size_t N>
    void Foo<N>::bar() {
    ...
    };
    
    for (const auto & size: {1,2,7,9})
        template struct Foo<size>;
    

    现在,我正在手动执行此操作(为每种类型安装),但这很容易出错,因为我有几个文件应该定义为相同的大小。

    我知道我可以将所有内容移到头文件中,并使用一些 enable_if 选择有效的大小。但是,我想隐藏实现细节。因此,目前的做法。

    编辑:

    FWIW,我希望避免宏。我想如果你想要一系列的变量(例如1,2,3,4…),这样的方法会有效的:

    template<template<size_t> class E, size_t I = 1, std::enable_if_t<I >= 5> *unused = nullptr>
    bool instatiator() {
      return true;
    }
    
    template<template<size_t> class E, size_t I = 1, std::enable_if_t<I < 5> *unused = nullptr>
    bool instatiator() {
      E<I> e;
      return instatiator<E, I + 1>();
    }
    
    bool unused = instatiator<Encoder>();
    

    但我似乎没法让它起作用。

    1 回复  |  直到 7 年前
        1
  •  8
  •   Angew is no longer proud of SO    7 年前

    你可以用 X macro

    有效_尺寸.hpp

    // Note: no include guards!!
    
    PROCESS_SIZE(1)
    PROCESS_SIZE(2)
    PROCESS_SIZE(7)
    PROCESS_SIZE(9)
    
    #undef PROCESS_SIZE
    

    食品.cpp

    // ...
    
    #define PROCESS_SIZE(n) template struct Foo<n>;
    #include "valid_sizes.hpp"
    

    // ...
    
    #define PROCESS_SIZE(n) some_other_use_of<n>;
    #include "valid_sizes.hpp"
    

    或者,您可以使用Boost.预处理器:

    过程_尺寸.hpp

    #pragma once
    
    #define PROCESS_SIZES(macro, data) BOOST_PP_SEQ_FOR_EACH(macro, data, (1)(2)(7)(9))
    

    #define INSTANTIATE_CLASS(r, Name, size) template class Name<size>;
    

    #include "process_sizes.hpp"
    
    // ...
    
    PROCESS_SIZES(INSTANTIATE_CLASS, Foo)
    

    酒吧cpp

    #include "process_sizes.hpp"
    
    // ...
    
    PROCESS_SIZES(INSTANTIATE_CLASS, Bar)
    
    #define OTHER_SIZE_BASED_WORK(r, data, size) other_use_of<size>;
    PROCESS_SIZES(OTHER_SIZE_BASED_WORK, whatever)
    

    请注意,显式实例化定义必须出现在命名空间范围内,因此不可能像尝试的那样将它们放在函数中 instantiator .

    并且还要注意,隐式实例化(例如在需要定义它的上下文中引用类所导致的)在翻译单元之外是不“可见的”,因此它不能用作显式实例化的替代品。

        2
  •  1
  •   amlucas    7 年前

    除了@Angew回答: xmacros可以有不同的方式,允许包含保护,也可以避免 #include 在代码的中间:

    #pragma once
    
    #define SIZES_TABLE(OP)\
    OP(1) \
    OP(2) \
    OP(12)
    

    食品.cpp

    #include "valid_sizes.hpp"
    // ...
    #define INSTANTIATE(Size) template struct Foo<Size>;
    SIZES_TABLE(INSTANTIATE)
    #undef INSTANTIATE
    
        3
  •  1
  •   Mike van Dyke    7 年前

    您可以递归地实例化 Foo 使用helper类初始化。不幸的是,您需要为 在构造函数中(虽然不会调用方法),为了向链接器提供定义:

    // foo.cpp: 
    
    template <size_t S>
    struct recursive_helper {
      Foo<S> foo;
      recursive_helper<S-1> r_helper;
    
      recursive_helper() {
        foo.bar();
        foo.baz();
      }
    };
    
    template <>
    struct recursive_helper<0> {
      Foo<0> foo;
      recursive_helper() {
        foo.bar();
        foo.baz();
      };
    };
    

    然后实例化helper类: template struct recursive_helper<6>;