i kown it's about gtest framework, i can use gtest for my own demo but in leveldb repo i don't know how to build a single test file such as:leveldb/db/db_test.cc, it will report other confused errors.
precondition:
what i want is debug a single testfile such as db_test.cc.
i use vscode, this is part of my task.json which i think already contains all needed:
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"-I", "/root/wzy/code/cpp/leveldb/include",
"-I", "/root/wzy/code/cpp/leveldb",
"-I", "/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include",
"-L", "/root/wzy/code/cpp/leveldb/build",
"-lleveldb",
"-lsnappy",
"-pthread"
]
and build errors like these:
/usr/bin/g++ -fdiagnostics-color=always -g /root/wzy/code/cpp/leveldb/db/db_test.cc -o /root/wzy/code/cpp/leveldb/db/db_test -I /root/wzy/code/cpp/leveldb/include -I /root/wzy/code/cpp/leveldb -I /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include -L /root/wzy/code/cpp/leveldb/build -lleveldb -lsnappy -lpthread
In file included from /root/wzy/code/cpp/leveldb/db/db_test.cc:12:
/root/wzy/code/cpp/leveldb/db/db_impl.h:174:3: error: 'port' does not name a type
174 | port::Mutex mutex_;
| ^~~~
/root/wzy/code/cpp/leveldb/db/db_impl.h:176:3: error: 'port' does not name a type
176 | port::CondVar background_work_finished_signal_ GUARDED_BY(mutex_);
| ^~~~
In file included from /root/wzy/code/cpp/leveldb/db/db_test.cc:14:
/root/wzy/code/cpp/leveldb/db/version_set.h:181:41: error: 'port' has not been declared
181 | Status LogAndApply(VersionEdit* edit, port::Mutex* mu)
| ^~~~
/root/wzy/code/cpp/leveldb/db/version_set.h:181:52: error: expected ',' or '...' before '*' token
181 | Status LogAndApply(VersionEdit* edit, port::Mutex* mu)
| ^
In file included from /root/wzy/code/cpp/leveldb/db/db_test.cc:24:
/root/wzy/code/cpp/leveldb/util/mutexlock.h:25:22: error: 'port' has not been declared
25 | explicit MutexLock(port::Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
| ^~~~
/root/wzy/code/cpp/leveldb/util/mutexlock.h:25:33: error: expected ')' before '*' token
25 | explicit MutexLock(port::Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
| ~ ^
| )
/root/wzy/code/cpp/leveldb/util/mutexlock.h:34:3: error: 'port' does not name a type
34 | port::Mutex* const mu_;
| ^~~~
/root/wzy/code/cpp/leveldb/util/mutexlock.h: In destructor 'leveldb::MutexLock::~MutexLock()':
/root/wzy/code/cpp/leveldb/util/mutexlock.h:28:42: error: 'class leveldb::MutexLock' has no member named 'mu_'
28 | ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }
| ^~~
In file included from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h:75,
from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-function-mocker.h:42,
from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock.h:61,
from /root/wzy/code/cpp/leveldb/util/testutil.h:8,
from /root/wzy/code/cpp/leveldb/db/db_test.cc:25:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In member function 'testing::internal::FieldsAreMatcher<Inner>::operator testing::Matcher<T>() const':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:3165:49: error: 'IndexSequenceFor' was not declared in this scope; did you mean 'IndexSequence'?
3165 | new FieldsAreMatcherImpl<const Struct&, IndexSequenceFor<Inner...>>(
| ^~~~~~~~~~~~~~~~
| IndexSequence
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:3165:71: error: expected parameter pack before '...'
3165 | new FieldsAreMatcherImpl<const Struct&, IndexSequenceFor<Inner...>>(
| ^~~
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:3165:71: error: template argument 2 is invalid
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4291:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4291 | const internal::StringLike<T>& str) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4291:31: error: expected ',' or '...' before '<' token
4291 | const internal::StringLike<T>& str) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::StrEqualityMatcher<std::__cxx11::basic_string<char> > > testing::StrEq(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4293:61: error: 'str' was not declared in this scope; did you mean 'std'?
4293 | internal::StrEqualityMatcher<std::string>(std::string(str), true, true));
| ^~~
| std
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4299:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4299 | const internal::StringLike<T>& str) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4299:31: error: expected ',' or '...' before '<' token
4299 | const internal::StringLike<T>& str) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::StrEqualityMatcher<std::__cxx11::basic_string<char> > > testing::StrNe(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4301:61: error: 'str' was not declared in this scope; did you mean 'std'?
4301 | internal::StrEqualityMatcher<std::string>(std::string(str), false, true));
| ^~~
| std
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4307:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4307 | const internal::StringLike<T>& str) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4307:31: error: expected ',' or '...' before '<' token
4307 | const internal::StringLike<T>& str) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::StrEqualityMatcher<std::__cxx11::basic_string<char> > > testing::StrCaseEq(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4309:61: error: 'str' was not declared in this scope; did you mean 'std'?
4309 | internal::StrEqualityMatcher<std::string>(std::string(str), true, false));
| ^~~
| std
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4315:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4315 | const internal::StringLike<T>& str) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4315:31: error: expected ',' or '...' before '<' token
4315 | const internal::StringLike<T>& str) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::StrEqualityMatcher<std::__cxx11::basic_string<char> > > testing::StrCaseNe(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4317:19: error: 'str' was not declared in this scope; did you mean 'std'?
4317 | std::string(str), false, false));
| ^~~
| std
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4324:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4324 | const internal::StringLike<T>& substring) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4324:31: error: expected ',' or '...' before '<' token
4324 | const internal::StringLike<T>& substring) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::HasSubstrMatcher<std::__cxx11::basic_string<char> > > testing::HasSubstr(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4326:59: error: 'substring' was not declared in this scope; did you mean 'IsSubstring'?
4326 | internal::HasSubstrMatcher<std::string>(std::string(substring)));
| ^~~~~~~~~
| IsSubstring
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4332:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4332 | const internal::StringLike<T>& prefix) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4332:31: error: expected ',' or '...' before '<' token
4332 | const internal::StringLike<T>& prefix) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::StartsWithMatcher<std::__cxx11::basic_string<char> > > testing::StartsWith(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4334:60: error: 'prefix' was not declared in this scope; did you mean 'profil'?
4334 | internal::StartsWithMatcher<std::string>(std::string(prefix)));
| ^~~~~~
| profil
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: At global scope:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4340:21: error: 'StringLike' in namespace 'testing::internal' does not name a template type; did you mean 'Strings'?
4340 | const internal::StringLike<T>& suffix) {
| ^~~~~~~~~~
| Strings
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4340:31: error: expected ',' or '...' before '<' token
4340 | const internal::StringLike<T>& suffix) {
| ^
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In function 'testing::PolymorphicMatcher<testing::internal::EndsWithMatcher<std::__cxx11::basic_string<char> > > testing::EndsWith(int)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:4342:58: error: 'suffix' was not declared in this scope
4342 | internal::EndsWithMatcher<std::string>(std::string(suffix)));
| ^~~~~~
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h: In member function 'bool testing::internal::ExceptionMatcherImpl<Err>::MatchAndExplain(T&&, testing::MatchResultListener*) const':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:5150:77: error: no matching function for call to 'GetTypeName(const std::type_info&)'
5150 | *listener << "throws an exception of type " << GetTypeName(typeid(err));
| ^
In file included from /usr/include/gtest/internal/gtest-internal.h:67,
from /usr/include/gtest/gtest.h:62,
from /root/wzy/code/cpp/leveldb/db/db_test.cc:11:
/usr/include/gtest/internal/gtest-type-util.h:80:13: note: candidate: 'template<class T> std::string testing::internal::GetTypeName()'
80 | std::string GetTypeName() {
| ^~~~~~~~~~~
/usr/include/gtest/internal/gtest-type-util.h:80:13: note: template argument deduction/substitution failed:
In file included from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-spec-builders.h:75,
from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-function-mocker.h:42,
from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock.h:61,
from /root/wzy/code/cpp/leveldb/util/testutil.h:8,
from /root/wzy/code/cpp/leveldb/db/db_test.cc:25:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-matchers.h:5150:77: note: candidate expects 0 arguments, 1 provided
5150 | *listener << "throws an exception of type " << GetTypeName(typeid(err));
| ^
In file included from /root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock.h:63,
from /root/wzy/code/cpp/leveldb/util/testutil.h:8,
from /root/wzy/code/cpp/leveldb/db/db_test.cc:25:
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h: In member function 'decltype (testing::internal::InvokeArgument(get<index>(std::forward_as_tuple((forward<Args>)(args)...)), (declval<const Params&>)()...)) testing::internal::InvokeArgumentAction<index, Params>::operator()(Args&& ...) const':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h:519:47: error: 'FlatTupleConstructTag' was not declared in this scope
519 | internal::FlatTuple<Args&&...> args_tuple(FlatTupleConstructTag{},
| ^~~~~~~~~~~~~~~~~~~~~
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h: In function 'testing::internal::InvokeArgumentAction<index, typename std::decay<Params>::type ...> testing::InvokeArgument(Params&& ...)':
/root/wzy/code/cpp/leveldb/third_party/googletest/googlemock/include/gmock/gmock-more-actions.h:564:17: error: 'FlatTupleConstructTag' is not a member of 'testing::internal'
564 | internal::FlatTupleConstructTag{}, std::forward<Params>(params)...)};
| ^~~~~~~~~~~~~~~~~~~~~
/root/wzy/code/cpp/leveldb/db/db_test.cc: At global scope:
/root/wzy/code/cpp/leveldb/db/db_test.cc:61:3: error: 'port' does not name a type
61 | port::Mutex mu_;
| ^~~~
/root/wzy/code/cpp/leveldb/db/db_test.cc: In member function 'void leveldb::{anonymous}::AtomicCounter::IncrementBy(int)':
/root/wzy/code/cpp/leveldb/db/db_test.cc:48:18: error: 'mu_' was not declared in this scope
48 | MutexLock l(&mu_);
| ^~~
/root/wzy/code/cpp/leveldb/db/db_test.cc: In member function 'int leveldb::{anonymous}::AtomicCounter::Read()':
/root/wzy/code/cpp/leveldb/db/db_test.cc:52:18: error: 'mu_' was not declared in this scope
52 | MutexLock l(&mu_);
| ^~~
/root/wzy/code/cpp/leveldb/db/db_test.cc: In member function 'void leveldb::{anonymous}::AtomicCounter::Reset()':
/root/wzy/code/cpp/leveldb/db/db_test.cc:56:18: error: 'mu_' was not declared in this scope
56 | MutexLock l(&mu_);
thanks #Tsyvarev, I defined a LEVELDB_PLATFORM_POSIX in source and this "prot" err is missing, but other errs still exist, I will keep doing this till I can GDB a single gtest file.
Related
#include <iostream>
#include <string>
typedef std::string S;
template <typename T>
static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
bool assigned = false;
if (!assigned) {
// invoke creationSpren with passed arguments
// assign
}
}
int main()
{
auto& xx = []() {
return new std::string("abc");
};
auto& zzz = getOrCreate<S>(xx);
}
note: this code does not compile, that is the problem I am trying to solve.
however, I wrote this minimum example to illustrate the problem, it is as barebones as possible.
What I'm trying to achieve is simple, to use lambdas to achieve lazy initialization of an object, when it is needed (i.e. when a retrieve fails, it calls the lambda and assigns the object (i.e. stores it) and returns it)
What I have problems with, as I have no experience with lambdas is both the signatures.
That is what I am asking, how to write the 2 lambda signatures. thanks.
and yes, it needs to be templated.
verbatim errors
<source>: In lambda function:
<source>:7:45: error: expected '{' before ')' token
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ^
<source>: At global scope:
<source>:7:46: error: expected ')' before 'creationSpren'
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ~ ^~~~~~~~~~~~~~
| )
<source>:7:63: error: expected ';' before '{' token
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ^~
| ;
<source>: In function 'int main()':
<source>:18:16: error: cannot bind non-const lvalue reference of type 'main()::<lambda()>&' to an rvalue of type 'main()::<lambda()>'
18 | auto& xx = []() {
| ^~~~~~
19 | return new std::string("abc");
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 | };
| ~
<source>: In instantiation of 'std::__cxx11::basic_string<char>* getOrCreate<std::__cxx11::basic_string<char> >':
<source>:22:17: required from here
<source>:7:33: error: cannot convert '<lambda()>' to 'std::__cxx11::basic_string<char>*' in initialization
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ^~~~~~~~~~~~
| |
| <lambda()>
<source>:22:31: error: 'getOrCreate<std::__cxx11::basic_string<char> >' cannot be used as a function
22 | auto& zzz = getOrCreate<S>(xx);
| ~~~~~~~~~~~~~~^~~~
ASM generation compiler returned: 1
<source>: In lambda function:
<source>:7:45: error: expected '{' before ')' token
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ^
<source>: At global scope:
<source>:7:46: error: expected ')' before 'creationSpren'
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ~ ^~~~~~~~~~~~~~
| )
<source>:7:63: error: expected ';' before '{' token
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ^~
| ;
<source>: In function 'int main()':
<source>:18:16: error: cannot bind non-const lvalue reference of type 'main()::<lambda()>&' to an rvalue of type 'main()::<lambda()>'
18 | auto& xx = []() {
| ^~~~~~
19 | return new std::string("abc");
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 | };
| ~
<source>: In instantiation of 'std::__cxx11::basic_string<char>* getOrCreate<std::__cxx11::basic_string<char> >':
<source>:22:17: required from here
<source>:7:33: error: cannot convert '<lambda()>' to 'std::__cxx11::basic_string<char>*' in initialization
7 | static inline T* getOrCreate( ( []() -> auto) creationSpren *) {
| ^~~~~~~~~~~~
| |
| <lambda()>
<source>:22:31: error: 'getOrCreate<std::__cxx11::basic_string<char> >' cannot be used as a function
22 | auto& zzz = getOrCreate<S>(xx);
| ~~~~~~~~~~~~~~^~~~
Execution build compiler returned: 1
If you look at the standard library and their functions which takes a callable object, it uses templates.
I recommend that for your function as well:
template<typename T, typename F>
static inline T* getOrCreate(F creationSpren)
{
// ...
}
There's another problem with your current function: The variable assigned is a normal local variable. It will be created and initialized to false each time getOrCreate is called.
You need to make it a static local variable.
If you need to pass argument to getOrCreate that are then forwarded to the creationSpren function, then use template parameter packs:
#include <utility>
#include <iostream>
template<typename T, typename F, typename ...A>
static inline T* getOrCreate(F creationSpren, A&& ...args)
{
creationSpren(std::forward<A>(args)...);
return nullptr;
}
int main()
{
auto lambda_noargs = []() { std::cout << "No arguments\n"; };
auto lambda_twoargs = [](int, int) { std::cout << "Two arguments\n"; };
getOrCreate<int>(lambda_noargs);
getOrCreate<int>(lambda_twoargs, 1, 2);
}
what you have now is just a complicated version of static local variable. (usually used in singleton)
int main(){
auto xx = []{
static std::string* v = new std::string("abc");
return v;
};
std::string* a = xx();
std::string* b = xx();
assert(a==b);
delete a; // manually cleanup as you `new` it
}
https://godbolt.org/z/GnsGaqnx3
I have a class and I wanna specialize a function in that class.
I need something like this:
class A
{
public:
template <typename T>
T fun()
{
throw new Exception("Unsupported template param");
}
template <>
bool fun<bool>()
{
return true;
}
template <>
float fun<float>()
{
return 5.6f;
}
template <>
double fun<double>()
{
return 5.684;
}
};
It works if I use the function without a class but if I put the function to the class I will get a lot of errors.
Example:
template <>
bool fun<bool>()
{
return true;
}
template <>
float fun<float>()
{
return 5.6f;
}
template <>
double fun<double>()
{
return 5.684;
}
It works. But when I declare fun in some class it doesn't work.
Errors: (Sorry for Russian language but my OS is translated to russian)
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:12:15: ошибка: явная специализация в не-namespace области «class A»
12 | template <>
| ^
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:13:10: ошибка: template-id «fun<bool>» in declaration of primary template
13 | bool fun<bool>()
| ^~~~~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:18:15: ошибка: явная специализация в не-namespace области «class A»
18 | template <>
| ^
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:19:11: ошибка: template-id «fun<float>» in declaration of primary template
19 | float fun<float>()
| ^~~~~~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:19:11: ошибка: «float A::fun()» cannot be overloaded with «bool A::fun()»
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:13:10: замечание: предыдущая декларация «bool A::fun()»
13 | bool fun<bool>()
| ^~~~~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:24:15: ошибка: явная специализация в не-namespace области «class A»
24 | template <>
| ^
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:25:12: ошибка: template-id «fun<double>» in declaration of primary template
25 | double fun<double>()
| ^~~~~~~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:25:12: ошибка: «double A::fun()» cannot be overloaded with «bool A::fun()»
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:13:10: замечание: предыдущая декларация «bool A::fun()»
13 | bool fun<bool>()
| ^~~~~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp: В функции-члене «T A::fun()»:
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:9:19: ошибка: expected type-specifier before «Exception»
9 | throw new Exception("unsupported colormodel");
| ^~~~~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp: В функции «int main(int, const char**)»:
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:33:18: ошибка: нет декларации «fun» в этой области видимости
33 | auto test1 = fun<float>();
| ^~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:33:22: ошибка: expected primary-expression before «float»
33 | auto test1 = fun<float>();
| ^~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:34:22: ошибка: expected primary-expression before «double»
34 | auto test2 = fun<double>();
| ^~~~~~
/home/aleksey/Документы/Проекты/tests/color-c/source/app.cpp:35:22: ошибка: expected primary-expression before «int»
35 | auto test3 = fun<int>();
I googled some similar questions about this purpose but most of the answers suggest only solutions with templates class, not template function in non-templated class. However, I've found this question. But the date of this question is 2014. Since the date of this one c++ get many changes. Maybe is there any way to specialize a function in a class without wrapping the function to separate class?
Say I have a dummy class like this:
class Stack
{
public:
template<typename T>
void push(T val)
{ (void)val; }
template<typename T>
T pop()
{ return 0; }
bool empty() const
{ return true; }
};
The AST dump of which looks like:
...
|-CXXRecordDecl 0x5610df147d60 <col:1, col:7> col:7 implicit class Stack
|-AccessSpecDecl 0x5610df147df0 <line:3:1, col:7> col:1 public
|-FunctionTemplateDecl 0x5610df1480e0 <line:4:3, line:6:16> line:5:8 push
| |-TemplateTypeParmDecl 0x5610df147e18 <line:4:12, col:21> col:21 referenced typename depth 0 index 0 T
| `-CXXMethodDecl 0x5610df148040 <line:5:3, line:6:16> line:5:8 push 'void (T)'
| |-ParmVarDecl 0x5610df147f00 <col:13, col:15> col:15 referenced val 'T'
| `-CompoundStmt 0x5610df1484f0 <line:6:3, col:16>
| `-CStyleCastExpr 0x5610df1484c8 <col:5, col:11> 'void' <ToVoid>
| `-DeclRefExpr 0x5610df148498 <col:11> 'T' lvalue ParmVar 0x5610df147f00 'val' 'T'
|-FunctionTemplateDecl 0x5610df148300 <line:8:3, line:10:15> line:9:5 pop
| |-TemplateTypeParmDecl 0x5610df148140 <line:8:12, col:21> col:21 referenced typename depth 0 index 0 T
| `-CXXMethodDecl 0x5610df148260 <line:9:3, line:10:15> line:9:5 pop 'T ()'
| `-CompoundStmt 0x5610df148538 <line:10:3, col:15>
| `-ReturnStmt 0x5610df148528 <col:5, col:12>
| `-IntegerLiteral 0x5610df148508 <col:12> 'int' 0
`-CXXMethodDecl 0x5610df1483e0 <line:12:3, line:13:18> line:12:8 empty 'bool () const'
`-CompoundStmt 0x5610df148570 <line:13:3, col:18>
`-ReturnStmt 0x5610df148560 <col:5, col:12>
`-CXXBoolLiteralExpr 0x5610df148550 <col:12> 'bool' true
Given access to the CXXRecordDecl node for Stack, how can I access the FunctionTemplateDecl objects for push and pop? CXXRecorDecl::methods only returns the method declaration for empty and I don't see any other functions that might be helpful. Do I have to match the function template declarations separately and then later associate them with the class declaration?
I believe I have now figured it out, I will answer my own question in case this is useful for someone else:
The way to do this is to first cast the given CXXRecordDecl to DeclContext, iterate over the contained declarations and try to cast them to FunctionTemplateDecl, pseudocode:
clang::CXXRecordDecl const *record = // ...
for (auto const *inner : static_cast<clang::DeclContext>(record)->decls()) {
auto const *member_function_template = llvm::dyn_cast<clang::FunctionTemplateDecl>(inner);
if (!member_function_template)
continue;
// do something useful
}
The following code https://godbolt.org/z/X0na5H fails to compile the rvalue version of the following code. I've used the BOOST_FOREACH extensibility guidelines I found here
In short I can't seem to get boost_foreach working with noncopyabe rvalues. Is this even possible?
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
#include <vector>
struct IdentityOp : std::vector<int>, boost::noncopyable {
IdentityOp(std::vector<int> && v):std::vector<int>(std::move(v)){}
};
namespace boost { namespace foreach
{
template <>
struct is_noncopyable< IdentityOp >
: mpl::true_
{
};
}}
#define BGS_TEST_LVALUE
// At global scope...
inline boost::mpl::true_ *
boost_foreach_is_noncopyable( IdentityOp *&, boost::foreach::tag )
{
return 0;
}
int main(){
std::vector<int> v;
#ifdef BGS_TEST_LVALUE
// LVALUE VERSION
IdentityOp op(std::move(v));
BOOST_FOREACH(const auto & a, op)
#else
// RVALUE VERSION
BOOST_FOREACH(const auto & a, IdentityOp(std::move(v)))
#endif
{}
}
shows the problem. If I define BGS_TEST_LVALUE then the code compiles. If I don't define it I get the error.
In file included from <source>:2:
/celibs/boost_1_70_0/boost/foreach.hpp: In instantiation of 'boost::foreach_detail_::auto_any<T> boost::foreach_detail_::contain(const T&, mpl_::true_*) [with T = IdentityOp; mpl_::true_ = mpl_::bool_<true>]':
<source>:34:5: required from here
/celibs/boost_1_70_0/boost/foreach.hpp:632:25: error: use of deleted function 'boost::foreach_detail_::auto_any<IdentityOp>::auto_any(boost::foreach_detail_::auto_any<IdentityOp>&&)'
632 | return auto_any<T>(t);
| ^
/celibs/boost_1_70_0/boost/foreach.hpp:253:8: note: 'boost::foreach_detail_::auto_any<IdentityOp>::auto_any(boost::foreach_detail_::auto_any<IdentityOp>&&)' is implicitly deleted because the default definition would be ill-formed:
253 | struct auto_any : auto_any_base
| ^~~~~~~~
/celibs/boost_1_70_0/boost/foreach.hpp:253:8: error: call of overloaded 'IdentityOp(IdentityOp)' is ambiguous
<source>:8:5: note: candidate: 'IdentityOp::IdentityOp(std::vector<int>&&)'
8 | IdentityOp(std::vector<int> && v):std::vector<int>(std::move(v)){}
| ^~~~~~~~~~
<source>:7:9: note: candidate: 'IdentityOp::IdentityOp(const IdentityOp&)' <deleted>
7 | struct IdentityOp : std::vector<int>, boost::noncopyable {
| ^~~~~~~~~~
<source>:7:9: note: candidate: 'IdentityOp::IdentityOp(IdentityOp&&)' <deleted>
In file included from <source>:2:
/celibs/boost_1_70_0/boost/foreach.hpp: In instantiation of 'boost::foreach_detail_::auto_any<T>::auto_any(const T&) [with T = IdentityOp]':
/celibs/boost_1_70_0/boost/foreach.hpp:632:12: required from 'boost::foreach_detail_::auto_any<T> boost::foreach_detail_::contain(const T&, mpl_::true_*) [with T = IdentityOp; mpl_::true_ = mpl_::bool_<true>]'
<source>:34:5: required from here
/celibs/boost_1_70_0/boost/foreach.hpp:256:15: error: use of deleted function 'IdentityOp::IdentityOp(const IdentityOp&)'
256 | : item(t)
| ^
<source>:7:9: note: 'IdentityOp::IdentityOp(const IdentityOp&)' is implicitly deleted because the default definition would be ill-formed:
7 | struct IdentityOp : std::vector<int>, boost::noncopyable {
| ^~~~~~~~~~
<source>:7:9: error: use of deleted function 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)'
In file included from /celibs/boost_1_70_0/boost/noncopyable.hpp:15,
from /celibs/boost_1_70_0/boost/foreach.hpp:72,
from <source>:2:
/celibs/boost_1_70_0/boost/core/noncopyable.hpp:49:7: note: declared here
49 | noncopyable( const noncopyable& ) = delete;
| ^~~~~~~~~~~
Compiler returned: 1
https://godbolt.org/z/X0na5H
I have want to build a shared object/shared library to be used by an executable later on.
I have a directory with my own *.cpp as well as the corresponding *.h files.
All the files are located in the same directory as my makefile (-I.):
#makefile to create shared library w/o executable from own headers and tesseract
CC = g++
INCL = -I. -I/usr/include/tesseract/ -I/usr/include/leptonica/
CFLAGS= -Wall -g -c -fPIC
LDFLAGS = -shared
LIBS = libtesseract.a liblept.a
RM = rm -f
TARGET_LIB = libTargetLib.so
SRCS = *.cpp
OBJS = $(SRCS:.cpp=.o)
.PHONY: all
all: ${TARGET_LIB}
$(TARGET_LIB): $(OBJS)
$(CC) $(LDFLAGS) $(INCL) -Wl,-rpath=/usr/lib/x86_64-linux-gnu/ -o $(TARGET_LIB) $^ -L/usr/lib/x86_64-linux-gnu/ -llept -ltesseract
$(OBJS): $(SRCS)
$(CC) $(CFLAGS) $(SRCS)
The library files to be linked, libtesseract.a and liblept.a are in the location /usr/lib/x86_64-linux-gnu, I doublechecked.
I am aware of this problem: ambiguous symbol File: tesscallback.h so I also commented out the correspondent lines.
When I run make, I get this error (tons of lines more):
In file included from /usr/include/tesseract/baseapi.h:34:0,
from file1.h:16,
from file1.cpp:4: /usr/include/tesseract/tesscallback.h:296:12: error: expected
nested-name-specifier before ‘remove_reference’ typename
remove_reference::type p1_;
^~~~~~~~~~~~~~~~ /usr/include/tesseract/tesscallback.h:296:12: error: expected ‘;’ at
end of member declaration
/usr/include/tesseract/tesscallback.h:296:28: error: expected
unqualified-id before ‘<’ token typename remove_reference::type
p1_;
^ /usr/include/tesseract/tesscallback.h: In constructor ‘_ConstTessMemberResultCallback_1_0::_ConstTessMemberResultCallback_1_0(const T*,
_ConstTessMemberResultCallback_1_0::MemberSignature, P1)’: /usr/include/tesseract/tesscallback.h:301:29: error: class
‘_ConstTessMemberResultCallback_1_0’ does not have any
field named ‘p1_’
member_(member), p1_(p1) { }
^~~ /usr/include/tesseract/tesscallback.h: In member function ‘virtual R
_ConstTessMemberResultCallback_1_0::Run()’: /usr/include/tesseract/tesscallback.h:305:38: error: ‘p1_’ was not
declared in this scope
R result = (object_->*member_)(p1_);
^~~ /usr/include/tesseract/tesscallback.h:308:38: error: ‘p1_’ was not
declared in this scope
R result = (object_->member_)(p1_);
^~~ /usr/include/tesseract/tesscallback.h: At global scope:
/usr/include/tesseract/tesscallback.h:326:12: error: expected
nested-name-specifier before ‘remove_reference’ typename
remove_reference::type p1_;
^~~~~~~~~~~~~~~~ /usr/include/tesseract/tesscallback.h:326:12: error: expected ‘;’ at
end of member declaration
/usr/include/tesseract/tesscallback.h:326:28: error: expected
unqualified-id before ‘<’ token typename remove_reference::type
p1_;
^ /usr/include/tesseract/tesscallback.h: In constructor ‘_ConstTessMemberResultCallback_1_0::_ConstTessMemberResultCallback_1_0(const T,
_ConstTessMemberResultCallback_1_0::MemberSignature, P1)’: /usr/include/tesseract/tesscallback.h:331:29: error: class
‘_ConstTessMemberResultCallback_1_0’ does not have
any field named ‘p1_’
member_(member), p1_(p1) { }
^~~ /usr/include/tesseract/tesscallback.h: In member function ‘virtual
void _ConstTessMemberResultCallback_1_0::Run()’:
/usr/include/tesseract/tesscallback.h:335:27: error: ‘p1_’ was not
declared in this scope
(object_->*member_)(p1_);
^~~ /usr/include/tesseract/tesscallback.h:337:27: error: ‘p1_’ was not
declared in this scope
(object_->*member_)(p1_);
When I do not comment it out (i. e., lines still there), I get:
In file included from /usr/include/tesseract/baseapi.h:34:0,
from process_houghlines.h:18,
from process_houghlines.cpp:3: /usr/include/tesseract/tesscallback.h:278:29: error:
‘remove_reference’ is not a class template template
struct remove_reference { typedef T type; };
^~~~~~~~~~~~~~~~ /usr/include/tesseract/tesscallback.h:278:29: error: redefinition of
‘struct remove_reference’
/usr/include/tesseract/tesscallback.h:277:29: note: previous
definition of ‘struct remove_reference’ template
struct remove_reference { typedef T type; };
^~~~~~~~~~~~~~~~ /usr/include/tesseract/tesscallback.h:296:12: error: expected
nested-name-specifier before ‘remove_reference’ typename
remove_reference::type p1_;
^~~~~~~~~~~~~~~~ /usr/include/tesseract/tesscallback.h:296:12: error: expected ‘;’ at
end of member declaration
/usr/include/tesseract/tesscallback.h:296:28: error: expected
unqualified-id before ‘<’ token typename remove_reference::type
p1_;
^ /usr/include/tesseract/tesscallback.h: In constructor ‘_ConstTessMemberResultCallback_1_0::_ConstTessMemberResultCallback_1_0(const T*,
_ConstTessMemberResultCallback_1_0::MemberSignature, P1)’: /usr/include/tesseract/tesscallback.h:301:29: error: class
‘_ConstTessMemberResultCallback_1_0’ does not have any
field named ‘p1 ’
member_(member), p1_(p1) { }
^~~ /usr/include/tesseract/tesscallback.h: In member function ‘virtual R
_ConstTessMemberResultCallback_1_0::Run()’: /usr/include/tesseract/tesscallback.h:305:38: error: ‘p1_’ was not
declared in this scope
R result = (object_->*member_)(p1_);
^~~ /usr/include/tesseract/tesscallback.h:308:38: error: ‘p1_’ was not
declared in this scope
R result = (object_->member_)(p1_);
^~~ /usr/include/tesseract/tesscallback.h: At global scope:
/usr/include/tesseract/tesscallback.h:326:12: error: expected
nested-name-specifier before ‘remove_reference’ typename
remove_reference::type p1_;
^~~~~~~~~~~~~~~~ /usr/include/tesseract/tesscallback.h:326:12: error: expected ‘;’ at
end of member declaration
/usr/include/tesseract/tesscallback.h:326:28: error: expected
unqualified-id before ‘<’ token typename remove_reference::type
p1_;
^ /usr/include/tesseract/tesscallback.h: In constructor ‘_ConstTessMemberResultCallback_1_0::_ConstTessMemberResultCallback_1_0(const T,
_ConstTessMemberResultCallback_1_0::MemberSignature, P1)’: /usr/include/tesseract/tesscallback.h:331:29: error: class
‘_ConstTessMemberResultCallback_1_0’ does not have
any field named ... (reoccurring error)
The files file1.h and file1.cpp:
...
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
...
and
...
#include "file1.h"
...
The files file2.h and file2.cpp:
...
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
...
and
...
#include "file2.h"
...
I dont even understand, why the errors differ, since the headers are to the extend of using Tesseract just equal and one time the error occurs in one, than in the other file.
Thank you so much for any help.