小编Joh*_*itb的帖子

特定成员的模板专业化?

是否可以专门化模板类的特定成员?就像是:

template <typename T,bool B>
struct X
{
    void Specialized();
};

template <typename T>
void X<T,true>::Specialized()
{
    ...
}

template <typename T>
void X<T,false>::Specialized()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

当然,这段代码无效.

c++ templates c++-faq specialization

24
推荐指数
2
解决办法
6822
查看次数

为什么我的模板不接受初始化列表

我创建了一个模板如下

template<typename T>
void f(T const& t) { }
Run Code Online (Sandbox Code Playgroud)

我希望这可以通过容器调用,也可以通过初始化列表调用.我认为这将是initializer_list<int>,如下调用.

f({1, 2, 3});
Run Code Online (Sandbox Code Playgroud)

但GCC表现得好像不符合标准

m.cpp: In function 'int main()':
m.cpp:6:25: warning: deducing 'const T' as 'const std::initializer_list<int>'
m.cpp:4:6: warning:   in call to 'void f(const T&) [with T = std::initializer_list<int>]'
m.cpp:6:25: warning:   (you can disable this with -fno-deduce-init-list)
Run Code Online (Sandbox Code Playgroud)

谁能解释我如何在没有警告的情况下完成这项工作?谢谢!

c++ initializer-list c++11

24
推荐指数
1
解决办法
3839
查看次数

从初始化列表初始化,但没有{{{{{{{{{}}}}}}}}?

我最近遇到了初始化列表的一些问题.考虑一个存储类似地图数据的程序

struct MyMapLike {
  MyMapLike(std::map<std::string, int> data)
    :data(std::move(data))
  { }

private:
  std::map<std::string, int> data;
};
Run Code Online (Sandbox Code Playgroud)

这看起来很直接.但是在初始化时,它会变得难看.我想让它看起来像

MyMapLike maps = { { "One", 1 }, { "Two", 2 } };
Run Code Online (Sandbox Code Playgroud)

但是编译器并不想接受这一点,因为上面意味着它应该寻找一个两个参数的构造函数,可以接受{ "One", 1 }{ "Two", 2 }分别.我需要添加额外的大括号,使它看起来像一个单参数构造函数接受{ { ... }, { ... } }

MyMapLike maps = { { { "One", 1 }, { "Two", 2 } } };
Run Code Online (Sandbox Code Playgroud)

我不想那样写.由于我有类似map的类,并且初始化程序具有映射列表的抽象值,因此我想使用前一版本,并且独立于任何此类实现细节,例如构造函数的嵌套级别.

一个解决方法是声明一个初始化列表构造函数

struct MyMapLike {
  MyMapLike(std::initializer_list< 
    std::map<std::string, int>::value_type
    > vals)
    :data(vals.begin(), vals.end())
  { }

  MyMapLike(std::map<std::string, int> data) …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list c++11

24
推荐指数
3
解决办法
3359
查看次数

如何使用extern模板

我一直在查看C++ 0x的N3291工作草案.我对extern模板感到好奇.第14.7.3节规定:

除了内联函数和类模板特化之外,显式实例化声明具有抑制它们引用的实体的隐式实例化的效果.

仅供参考:"明确的实例化声明"一词是标准的extern template.这已在第14.7.2节中定义.

这听起来像是在说如果你使用extern template std::vector<int>,那么做任何通常隐式实例化的事情std::vector<int>都不会这样做.

下一段更有趣:

如果实体是同一翻译单元中的显式实例化声明和显式实例化定义的主题,则该定义应遵循声明.作为显式实例化声明的主体并且以在否则将导致翻译单元中的隐式实例化(14.7.1)的方式中使用的实体应该是程序中某处的显式实例化定义的主题; 否则该程序格式错误,无需诊断.

仅供参考:术语"显式实例化定义"是这些事物的标准说法:template std::vector<int>.也就是说,没有了extern.

对我来说,这两件事说extern template防止了隐式实例化,但它并没有阻止显式实例化.所以,如果你这样做:

extern template std::vector<int>;
template std::vector<int>;
Run Code Online (Sandbox Code Playgroud)

第二行有效地否定了第一行,明确地做了第​​一行隐含发生的事情.

问题是:Visual Studio 2008似乎不同意.我想要使​​用的方法extern template是阻止用户隐式实例化某些常用模板,以便我可以在.cpp文件中显式实例化它们以减少编译时间.模板只会实例化一次.

问题是我必须在VS2008中围绕它们#ifdef.因为如果单个翻译单元看到extern和非extern版本,它将使extern版本获胜并且没有人会实例化它.然后是链接器错误.

所以,我的问题是:

  1. 根据C++ 0x,正确的行为是什么?应该extern template防止明确的实例化吗?
  2. 如果上一个问题的答案是它不应该,那么VS2008是错误的(被授予,它在规范之前写得很好,所以它不像是他们的错).VS2010如何处理这个问题?它是否实现了正确的extern template行为?

c++ templates visual-studio-2008 explicit-instantiation c++11

24
推荐指数
1
解决办法
1万
查看次数

变种模板

C++ 0x将允许模板采用任意数量的参数.除了实现元组之外,此功能的最佳用途是什么?

c++ templates c++11

23
推荐指数
1
解决办法
6058
查看次数

如果在演绎期间无法解析函数的地址,是SFINAE还是编译器错误?

在C++ 0x中,简化了SFINAE规则,使得在演绎的"直接上下文"中出现的任何无效表达式或类型不会导致编译器错误,而是导致演绎失败(SFINAE).

我的问题是:
如果我采用重载函数的地址并且无法解决,那么在演绎的直接上下文中是否会失败?
(如果它无法解决,那么它是一个硬错误还是SFINAE)?

以下是一些示例代码:

struct X
{
  // template<class T> T* foo(T,T); // lets not over-complicate things for now
  void foo(char);
  void foo(int);
};


template<class U> struct S
{
  template<int> struct size_map 
  { typedef int type; };


// here is where we take the address of a possibly overloaded function
  template<class T> void f(T, 
      typename size_map<sizeof(&U::foo)>::type* = 0); 


  void f(...);
};

int main()
{
  S<X> s;

// should this cause a compiler error because 'auto T = &X::foo' …
Run Code Online (Sandbox Code Playgroud)

c++ templates sfinae overload-resolution c++11

23
推荐指数
1
解决办法
1万
查看次数

如果派生类析构函数抛出异常,基类析构函数会发生什么

它刚好发生在我身上,我想知道在下列情况下如何释放资源.

class Base {
  Resource *r;

public:
  Base() { /* ... */ }
  ~Base() {
    delete r; 
  }
};

class Derived : public Base {
public:
  Derived() { /* ... */ }
  ~Derived() {
    /* Suddenly something here throws! */
  }
};

int main() {
  try {
    Derived d;
  } catch(...) {
    /* what happened with Base::r !? */
  }
}
Run Code Online (Sandbox Code Playgroud)

如果派生类析构函数抛出,是否会调用基类析构函数?或者会有泄漏吗?

c++ destructor memory-leaks exception

23
推荐指数
1
解决办法
2117
查看次数

模仿GCC的__builtin_unreachable?

我得到了很多关于交换机的警告,这些交换机仅部分覆盖了切换的枚举范围.为此,我想有一个"默认"所有这些开关,并将__builtin_unreachable(GCC内置),在这种情况下,让编译器知道这种情况是不可达.

但是,我才知道GCC4.3还不支持内置版.有没有什么好方法可以模仿这个功能?我考虑过取消引用空指针,但这可能有其他不良影响/警告等.你有更好的主意吗?

c++ gcc unreachable-code

23
推荐指数
2
解决办法
8048
查看次数

为什么使用这个POD结构作为基类是危险的?

我和一位同事进行了这次谈话,结果很有趣.假设我们有以下POD课程

struct A { 
  void clear() { memset(this, 0, sizeof(A)); } 

  int age; 
  char type; 
};
Run Code Online (Sandbox Code Playgroud)

clear旨在清除所有成员,设置为0(按字节顺序).如果我们A用作基类会出现什么问题?这里有一个微妙的漏洞来源.

c++ pod memset

23
推荐指数
2
解决办法
1164
查看次数

为什么对std :: tuple实现使用递归继承不好?

这个问题上,Howard Hinnant说

std :: tuple的一些实现使用递归继承.但好的却没有.;-)

有人可以对此有所了解吗?

c++ c++11 stdtuple

23
推荐指数
1
解决办法
2880
查看次数