当包含在至少两个翻译单元(cpp文件)上时,这一小段代码会触发链接器的愤怒:
# ifndef MAXIMUM_HPP
# define MAXIMUM_HPP
template<typename T>
T maximum(const T & a, const T & b)
{
return a > b ? a : b ;
}
/* dumb specialization */
template<>
int maximum(const int & a, const int & b)
{
return a > b ? a : b ;
}
# endif // MAXIMUM_HPP
Run Code Online (Sandbox Code Playgroud)
但是用一个翻译单元编译和链接很好.如果我删除了专业化,它在所有情况下都能正常工作.这是链接器消息:
g++ -o test.exe Sources\test.o Sources\other_test.o
Sources\other_test.o:other_test.cpp:(.text+0x0): multiple definition of `int maximum<int>(int const&, int const&)'
Sources\test.o:test.cpp:(.text+0x14): first defined here
Run Code Online (Sandbox Code Playgroud)
模板是否允许多次实例化?如何解释此错误以及如何解决?
谢谢你的建议!
我不是在问C++异常是否安全通过C代码传播,也不会在发生这种情况时发生什么.我已经在SO(阅读下面的问题1,2,3)和本FAQ.我问如何继续:
让我说明一下我的想法:
Say libfoo
是一个C库,我想在我的bar
C++程序中使用它.libfoo
需要一个foo_callback
我必须提供的回调函数.我的回调中使用的函数和方法可能抛出异常,所以我写道:
void my_callback(void)
{
try
{
// Do processing here.
}
catch(...)
{
// Catch anything to prevent an exception reaching C code.
// Fortunately, libfoo provides a foo_error function to
// signal errors and stop processing.
foo_error() ;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我使用我的回调,如下所示:
// The bar program.
int main()
{
// Use libfoo function to set the desired callback
foo_set_callback(&my_callback) ; …
Run Code Online (Sandbox Code Playgroud) 我偶然发现了一个奇怪的编译问题.我想使用处理字符串列表std::for_each
.以下简化代码说明了问题:
# include <list>
# include <string>
# include <algorithm>
using namespace std ;
void f(wstring & str)
{
// process str here
}
void g(wstring & str, int dummy = 0)
{
// process str here, same as f, just added a second default dummy argument
}
int main(int, char*[])
{
list<wstring> text ;
text.push_back(L"foo") ;
text.push_back(L"bar") ;
for_each(text.begin(), text.end(), f) ; // OK, fine :)
for_each(text.begin(), text.end(), g) ; // Compilation error, complains about
// g …
Run Code Online (Sandbox Code Playgroud) 以下代码:
main.cpp:
# include <iostream>
# include <csetjmp>
# include <stdexcept>
using namespace std ;
void do_work(jmp_buf context)
{
try
{
throw runtime_error("Ouch !") ;
}
catch(exception & e)
{
}
longjmp(context, -1) ; //BP1
}
int main(int, char *[])
{
jmp_buf context ;
try
{
if( setjmp(context) != 0 )
{
throw runtime_error("Oops !") ; //BP2
}
do_work(context) ;
}
catch(exception & e)
{
cout << "Caught an exception saying : " << e.what() …
Run Code Online (Sandbox Code Playgroud) 我正在使用boost :: multi_index_container来提供随机访问和对元素集合的基于散列的访问.我想更改元素的随机访问索引,而不更改基于哈希的索引.
这是一段代码:
# include <string>
# include <boost/multi_index_container.hpp>
# include <boost/multi_index/random_access_index.hpp>
# include <boost/multi_index/hashed_index.hpp>
# include <boost/multi_index/member.hpp>
using namespace std ;
using namespace boost ;
using namespace boost::multi_index ;
// class representing my elements
class Element
{
public :
Element(const string & new_key) : key(new_key) {}
string key ; // the hash-based index in the multi_index_container
// ... many stuff skipped
private :
// ... many stuff skipped
} ;
typedef multi_index_container<
Element,
indexed_by<
random_access< >, …
Run Code Online (Sandbox Code Playgroud) 我正在编写一个控制台程序,它使用DirectSound API来渲染一些音频数据.在按照DirectSound编程指南(来自Microsoft)时,我偶然发现了一个奇怪的问题.根据文件:
创建设备对象后,必须使用IDirectSound8 :: SetCooperativeLevel方法设置设备的协作级别.除非你这样做,否则不会听到任何声音.
问题是我正在编写一个控制台程序,并且SetCooperativeLevel
需要HWND作为第一个参数.我没有在控制台程序中处理任何HWND.我尝试提供一个空指针,但它失败了一个DSERR_INVALIDPARAM
错误代码.
应该IDirectSound8::SetCooperativeLevel
在控制台程序中提供什么HWND值?计划的音频部分计划构建为共享库,因此几乎不知道"外部"程序.
谢谢你的建议!
注意:我知道有一个更好的解决方案可以简单地渲染音频,比如使用SDL,OpenAL,SFML(基于OpenAL),但对于我当前的项目,DirectSound是强制执行的.
编辑:我发现Microsoft工程师发来的消息消除了SetCooperativeLevel
在创建GLOBAL_FOCUS缓冲区时使用桌面窗口或控制台窗口作为HWND的疑虑.
显然,标准容器没有公共基类,也没有通用接口,尽管方法名称是同构的.
问题:我必须用一组独特类型的对象填充容器.容器可以是a std::list
,a std::vector
或a std::deque
,也可能是其他一些自定义容器.以下代码是最佳解决方案吗?
# include <string>
# include <iostream>
# include <list>
# include <vector>
# include <deque>
/*
* Fill a container with two strings. The container
* must expose the `clear` and `push_back` methods.
*/
template<typename T>
void f(T & t)
{
t.clear() ;
t.push_back("Alice") ;
t.push_back("Bob") ;
}
int main(int, char*[])
{
std::list<std::string> l ;
std::vector<std::string> v ;
std::deque<std::string> q ;
f(l) ; // fill the list
f(v) ; // fill the …
Run Code Online (Sandbox Code Playgroud) 标题说明了一切。之后包括<csetjmp>
,longjmp
和jmp_buf
都在std
命名空间中,但setjmp
不是。我在 MinGW4.5 和 MSVC10 上验证了这一点。查看<csetjmp>
标题后,我无法弄清楚这个选择的原因。我一直假设每个<cheader>
文件都<header.h>
在std
命名空间中包装 a 。
我错了吗 ?setjmp
特殊情况背后的基本原理是什么?请赐教!
注意:我知道在 C++ 中滥用 setjmp/longjmp 的问题。
我想使用std::streamoff
和std::streamsize
类型而不会拉动iostream库的大部分内容.现在,我包括<iostream>
标题.还有更好的方法吗?