【问题标题】:Template varargs and explicit instantiation模板可变参数和显式实例化
【发布时间】:2014-09-13 12:33:24
【问题描述】:

我正在尝试同时使用几个新的 C++11 功能。

#include <iostream>
#include <vector>


// Trying out template varargs.
template<typename T, T... args>
struct Test
{
    // Using constexpr
    // I had assumed that with this I did not need to
    // explicitly create an object `values`
    // that the compiler will work this out at compile time.
    static constexpr T              values[] = {args...};
};

// Explicitly instantiate
// the template to force it to generate the appropriate code. 
template struct Test<int, 1, 2, 3>;


typedef Test<int, 1, 2, 3>  TestInt;

int main()
{
    // Silly test to see if it worked.
    std::cout << TestInt::values[0] << "\n";
}

这会导致链接器失败。

> g++ -std=c++11 tp.cpp
Undefined symbols for architecture x86_64:
  "Test<int, 1, 2, 3>::values", referenced from:
      _main in tp-f3440e.o
ld: symbol(s) not found for architecture x86_64

我尝试了几种显式定义values 数组的变体。但是没有一个编译成功。

任何帮助表示赞赏。

更新:

显然这是为@Nikos Athanasiou 编译的,这里有他的示例 http://coliru.stacked-crooked.com/a/474fd3183db003f1

那么这是一个已知的编译器错误吗?

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

【问题讨论】:

  • typedef 不会导致显式实例化。
  • 注意 values 仍未定义。只要在类定义中初始化的静态成员不被 ODR 使用,就应该没问题。
  • @chris:是的。这是我的问题,我该如何定义它。
  • @LokiAstari, Really, interesting.

标签: c++ templates c++11 variadic-templates constexpr


【解决方案1】:

values 不仅仅由初始化定义,而是因为constexpr,所以初始化需要保存在Test 内部:

template<typename T, T... args> 
constexpr T Test<T, args...>::values[];

有关适用于 GCC 4.9 和 Clang 3.4 的完整示例,请参阅 here

#include <iostream>
#include <vector>


// Trying out template varargs.
template<typename T, T... args>
struct Test
{
    // Using constexpr
    // I had assumed that with this I did not need to
    // explicitly create an object `values`
    // that the compiler will work this out at compile time.
    static constexpr T values[] = {args...};
};

template<typename T, T... args> 
constexpr T Test<T, args...>::values[];

// Explicitly instantiate
// the template to force it to generate the appropriate code. 
template struct Test<int, 1, 2, 3>;


typedef Test<int, 1, 2, 3>  TestInt;

int main()
{
    // Silly test to see if it worked.
    std::cout << TestInt::values[0] << "\n";
}

【讨论】:

  • 我确信我已经尝试过了。其中一次是我希望我在某种形式的源代码控制中尝试过每个版本,这样我就可以回过头来将我所做的每一次尝试与最终答案进行比较,以找出我犯的微妙错误。不过谢谢。
  • @LokiAstari,我知道这种感觉。
猜你喜欢
  • 2014-06-30
  • 2014-10-31
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多