Boost logo

Ublas :

Subject: [ublas] Linking error using "<<=" (assignment.hpp)
From: Bombardier, Yan (Yan.Bombardier_at_[hidden])
Date: 2011-11-16 12:59:04


Hi,

I am new to ublas and I am trying to initialize a matrix or a vector within the code itself, e.g. M=[1,2,3;4,5,6;7,8,9] in Matlab. I found many ways of addressing this, including the "storage_adaptor" method provided on http://www.guwi17.de/ublas/examples/. This approach works well, but as far as I understood, you need to create a C array first and I was looking for a more straightforward way to initialize my vectors/matrices.

I found another approach, consisting of using the assignment operator "<<=", e.g. M<<=1,2,3,4,5,6,7,8,9, given that the vector or matrix is properly declared with its dimensions. Using this approach, a user can directly populate the vector or matrix without a C array (this is what I was looking for...!). This approach works if the code is written in the main file (e.g. http://svn.boost.org/svn/boost/branches/release/libs/numeric/ublas/test/test_assignment.cpp), but I came across linking error with MSVC 10 when I use the assignment operator in different cpp/h files. I attached my test case (main.cpp; a.h, a.cpp).

I get the following errors when I compile this code using MSVC 10:

1>------ Build started: Project: TEST, Configuration: Debug Win32 ------
1>Build started 11/16/2011 11:47:08.
1>InitializeBuildStatus:
1> Creating "Debug\TEST.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1> main.cpp
1> a.cpp
1> Generating Code...
1>ManifestResourceCompile:
1> All outputs are up-to-date.
1>main.obj : error LNK2005: "class boost::numeric::ublas::begin1_manip __cdecl boost::numeric::ublas::begin1(void)" (?begin1_at_ublas@numeric_at_boost@@YA?AVbegin1_manip_at_123@XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::begin2_manip __cdecl boost::numeric::ublas::begin2(void)" (?begin2_at_ublas@numeric_at_boost@@YA?AVbegin2_manip_at_123@XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::next_row_manip __cdecl boost::numeric::ublas::next_row(void)" (?next_row_at_ublas@numeric_at_boost@@YA?AVnext_row_manip_at_123@XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::next_column_manip __cdecl boost::numeric::ublas::next_column(void)" (?next_column_at_ublas@numeric_at_boost@@YA?AVnext_column_manip_at_123@XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::traverse_policy::by_row_policy<struct boost::numeric::ublas::traverse_policy::wrap> __cdecl boost::numeric::ublas::traverse_policy::by_row(void)" (?by_row_at_traverse_policy_at_ublas@numeric_at_boost@@YA?AV?$by_row_policy_at_Uwrap@traverse_policy_at_ublas@numeric_at_boost@@@1234_at_XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::traverse_policy::by_row_policy<struct boost::numeric::ublas::traverse_policy::wrap> __cdecl boost::numeric::ublas::traverse_policy::by_row_wrap(void)" (?by_row_wrap_at_traverse_policy_at_ublas@numeric_at_boost@@YA?AV?$by_row_policy_at_Uwrap@traverse_policy_at_ublas@numeric_at_boost@@@1234_at_XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::traverse_policy::by_row_policy<struct boost::numeric::ublas::traverse_policy::no_wrap> __cdecl boost::numeric::ublas::traverse_policy::by_row_no_wrap(void)" (?by_row_no_wrap_at_traverse_policy_at_ublas@numeric_at_boost@@YA?AV?$by_row_policy_at_Uno_wrap_at_traverse_policy_at_ublas@numeric_at_boost@@@1234_at_XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::traverse_policy::by_column_policy<struct boost::numeric::ublas::traverse_policy::wrap> __cdecl boost::numeric::ublas::traverse_policy::by_column(void)" (?by_column_at_traverse_policy_at_ublas@numeric_at_boost@@YA?AV?$by_column_policy_at_Uwrap@traverse_policy_at_ublas@numeric_at_boost@@@1234_at_XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::traverse_policy::by_column_policy<struct boost::numeric::ublas::traverse_policy::wrap> __cdecl boost::numeric::ublas::traverse_policy::by_column_wrap(void)" (?by_column_wrap_at_traverse_policy_at_ublas@numeric_at_boost@@YA?AV?$by_column_policy_at_Uwrap@traverse_policy_at_ublas@numeric_at_boost@@@1234_at_XZ) already defined in a.obj
1>main.obj : error LNK2005: "class boost::numeric::ublas::traverse_policy::by_column_policy<struct boost::numeric::ublas::traverse_policy::no_wrap> __cdecl boost::numeric::ublas::traverse_policy::by_column_no_wrap(void)" (?by_column_no_wrap_at_traverse_policy_at_ublas@numeric_at_boost@@YA?AV?$by_column_policy_at_Uno_wrap_at_traverse_policy_at_ublas@numeric_at_boost@@@1234_at_XZ) already defined in a.obj
1>C:\Users\XXXXX\Desktop\TEST\Debug\TEST.exe : fatal error LNK1169: one or more multiply defined symbols found
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:04.06
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I am not the first one to report such error: https://svn.boost.org/trac/boost/ticket/6010 (reported 5 weeks ago)

The linking problem was addressed by adding "inline" for the problematic functions. This fix was however not included in Boost 1.48.

Now, here are my questions:

1. Am I using the "<<=" correctly?

2. Is there a reason why this fix was not implemented in 1.48?

3. Is there another (less intrusive) fix?

4. Is there a better way to initialize a ublas vector/matrix?

Thank you,
Yan