Forcing template function instantiation in class - c++

I have a function that is declared like:
template<typename T>
void MyFunction();
And a class:
template<typename T>
class MyClass
{
public:
typedef void (*Function_T)();
Function_T m_Func;
void DoSomething()
{
m_Func = &MyFunction<T>;
}
}
When I use the class, I undefined symbols error on MyFunction<T>.
If I change DoSomething to
void DoSomething()
{
m_Func = &MyFunction<T>;
return;
MyFunction<T>();
}
Everything works, but that looks like a workaround and will probably not work with optimization.
I cannot add
template void MyFunction<T>;
to the class because it says it cannot be in class. Is there any other way I can force instantiation of the function?
Edit:
I was able to write a test that fails, but in g++ it has a different message and actually a compiler error: http://ideone.com/RbMnh

Your code will work with optimization as well. Although, I don't know why simply m_Func = &MyFunction<T> doesn't work. GCC 4.3.4 compiles it fine. Which compiler you're using?
And you can also do this:
void DoSomething()
{
if ( false) MyFunction<T>();
m_Func = &MyFunction<T>;
return;
}
By the way, the function pointer type is incorrectly defined. It should be this:
typedef void (*Function_T)();
// ^^ put this!

Your code compiles fine for me using GCC, so I'm not sure if this solution solves your particular problem, but you can explicitly instantiate template functions like so:
// Template function defined:
template <typename T>
void MyFunction() {
// body
}
// Template function instantiated:
template void MyFunction<int>();

The issue can be either a compiler bug, or an error in the parts of the code that you are not showing. Try to build a minimal example that reproduces the problem, this is the minimal example that I have been able to produce, and compiles fine with both clang++ 2.8 and g++ 4.4/4.5:
drodriguez#drodriguez-desktop:/tmp$ cat test.cpp
#include <iostream>
template <typename T>
void function() {
}
template <typename T>
struct type {
typedef void (*Func)();
Func _f;
void f() {
_f = &function<T>;
}
};
int main() {
type<int> t;
t.f();
std::cout << t._f << std::endl;
}
drodriguez#drodriguez-desktop:/tmp$ /usr/bin/clang++ --version
clang version 2.8 (branches/release_28)
Target: x86_64-pc-linux-gnu
Thread model: posix
drodriguez#drodriguez-desktop:/tmp$ /usr/bin/clang++ -o test test.cpp && ./test
1
drodriguez#drodriguez-desktop:/tmp$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
drodriguez#drodriguez-desktop:/tmp$ g++-4.4 -o test test.cpp && ./test
1

Related

Lambdas, Is this keyword needed to disambiguate const/non-const member functions?

When I use MSVC to compile this program, I receive the error,
"Example::bar ambiguous call to overloaded function"
Then, I found that the this keyword was able to resolve the error. Surprised, I used rextester and found that both Clang and GCC were able to compile the program without the this keyword.
Here is the program in question.
#include <iostream>
class Example {
public:
Example() {
auto lambda = [this]() {
//this->bar<int>(); // Using this allows the program to compile and run successfully.
bar<int>(); // This doesn't work in MSVC
};
lambda();
}
template<typename T>
void bar() {
std::cout << "(non-const) bar\n";
}
template<typename t>
void bar() const {
std::cout << "(const) bar\n";
}
};
int main() {
Example example;
}
Ultimately I am asking, is this keyword needed in a lambda to disambiguate between const and non-const member functions and whether MSVC is correct or GCC and Clang are correct.
I am using Visual Studio 2017 and the full version of MSVC is 191627027

Symbol not found in debugger only, when having templated template argument

Given the following code as test.cpp,
Building using clang++ -c test.cpp -o test.o -g; clang++ test.o -g -all_load, setting breakpoint at return a.getValue(); and attempting to p a.getValue() from lldb:
Running llvm 3.8.0 on unix - works perfectly
Running xcode or llvm 8.1.0 on OSX - I get the following error:
error: Couldn't lookup symbols:
__ZNK4Test7MyClassILi2ELi3EE8getValueEv
Two interesting facts:
If I remove the last template argument - all works well
If I build directly without going through the .o file (clang++ test.cpp) = all goes well
Anyone has a clue what is going on, and how can it be fixed?
namespace Test{
template<class T>
class BLA{
public:
T getBlaValue() const{return 3;}
};
template <int N1, int N2, template<class T>class Impl = BLA>
class MyClass {
private:
public:
__attribute__((used))
int getValue() const
{
return 3;
}
};
}
int main()
{
Test::MyClass<2, 3> a;
return a.getValue();
}

Constructor that takes nulltpr_t: function definition does not declare parameters

I have the following code:
class C {
private:
void *data;
public:
constexpr C(nullptr_t) : data(nullptr) { }
C(int i) : data(new int(i)) { }
};
I have created a constructor which takes nullptr_t, so that I can have code similar to the following:
C foo(2);
// ...
foo = nullptr;
Code similar to this has worked previously on MSVC, however this code fails to compile on GCC 5.3.1 (using -std=c++14) with on the closing bracket of C(nullptr_t) with error: function definition does not declare parameters. Even if i give the parameter a name (in this case _), I get error: expected ')' before '_'. This also fails if the constexpr keyword is removed.
Why am I unable to declare such a constructor, and what are any possible workarounds?
You must be a fan of "using namespace std", and you just got tripped up by it:
constexpr C(std::nullptr_t) : data(nullptr) { }
gcc 5.3.1 compiles this, at --std=c++14 conformance level:
[mrsam#octopus tmp]$ cat t.C
#include <iostream>
class C {
private:
void *data;
public:
constexpr C(std::nullptr_t) : data(nullptr) { }
C(int i) : data(new int(i)) { }
};
[mrsam#octopus tmp]$ g++ -g -c --std=c++14 -o t.o t.C
[mrsam#octopus tmp]$ g++ --version
g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Is a friend function template defined in the class available for lookup? clang++ and g++ disagree

Here is the code:
struct foo {
template<typename T = void>
friend foo f() { return {}; }
};
int main() {
auto x = f(); // clang++ can't find it, g++ can.
}
clang++ 3.4 gives:
fni2.cpp:8:12: error: use of undeclared identifier 'f'
auto x = f(); // clang++ can't find it, g++ can.
^
1 error generated.
g++ 4.9.0 compiles it, but I don't think it should have. This is a related question, but there was no definitive answer. Section 15.4.2/2,4 discuss this, but neither of them say anything to suggest that friend function templates defined in-class should have different visibility from non-template friend functions defined in-class.
This is of academic interest to me only, though it did arise from a question by someone else who may have had an actual use case.
It looks like a g++ bug to me.
Yes, this is an error. I'm surprised it's finding the function. Apparently GCC fails entirely to hide function templates.
This C++03 example also compiles, so it could be a regression:
struct foo {
template<typename T >
friend void f( T ) { }
};
int main() {
f( 3 ); // clang++ can't find it, g++ can.
}

Using atomic<bool> to wait on two threads

Let's say I have a simple pool class:
template<typename Iterator, typename T>
class pool
{
public:
pool(std::vector<T> data) :
data_(data),
thread_1_finished(false),
thread_2_finished(false)
{}
void thread_1(Iterator, Iterator);
void thread_2(Iterator, Iterator);
void thread_3_method_1();
void thread_3_method_2();
void do_it();
private:
std::vector<T> data_;
std::mutex mut_;
std::condition_variable data_cond_;
threadsafe_queue<int> data_queue_;
std::atomic<bool> thread_1_finished;
std::atomic<bool> thread_2_finished;
};
The thread_3 needs to wait on the completion of thread_1 and thread_2, which is done by calling notify_all on the condition_variable data_cond, after setting thread_1_finished to true. Both thread_1, thread_2 do it this way:
template<typename Iterator, typename T>
void pool<Iterator, T>::thread_1(Iterator first, Iterator last)
{
sort_block<Iterator, T> s;
s(first, last);
std::lock_guard<std::mutex> lk(mut_);
thread_1_finished = true;
data_cond_.notify_all();
fprintf(stderr, "thread 1 finished.\n");
}
Now this doesn't compile:
template<typename Iterator, typename T>
void pool<Iterator, T>::thread_3_method_1()
{
std::unique_lock<std::mutex> lk(mut_);
data_cond_.wait(lk,
[this]()->bool
{
return (thread_1_finished && thread_2_finished);
});
}
In fact I get:
charles#ely:~/src/C/sandbox/waiting_on_two_threads$ make
makedepend -pobj/ -Y/dev/null -I. test.cpp 2>makedepend.err
g++ -c -g -w -std=c++11 -I. -I/home/charles/src/C/include -I/home/charles/src/C test.cpp -o obj/test.o
test.cpp: In lambda function:
test.cpp:126:38: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.7/README.Bugs> for instructions.
Preprocessed source stored into /tmp/ccU4V5nL.out file, please attach this to your bugreport.
make: *** [obj/test.o] Error 1
This compiles:
template<typename Iterator, typename T>
void pool<Iterator, T>::thread_3_method_1()
{
std::unique_lock<std::mutex> lk(mut_);
data_cond_.wait(lk,
[this]()->bool
{
return thread_1_finished;
});
data_cond_.wait(lk,
[this]()->bool
{
return thread_2_finished;
});
}
Why is this? I guess the second method will accomplish the same thing, considering the unique_lock, but I still don't get it.
charles#ely:~$ uname -a
Linux ely 3.2.0-24-generic #37-Ubuntu SMP Wed Apr 25 08:43:22 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
charles#ely:~$ g++ --version
g++ (Ubuntu/Linaro 4.7.0-7ubuntu3) 4.7.0
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.