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
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
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();
}
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.
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.
}
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.