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?
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
#include <iostream>
template<unsigned N>
struct FixedString
{
char buf[N + 1]{};
constexpr FixedString(const char (&s)[N])
{
for (unsigned i = 0; i != N; ++i)
buf[i] = s[i];
}
};
template<int, FixedString name>
class Foo
{
public:
auto hello() const { return name.buf; }
};
template<FixedString name>
class Foo<6, name>
{
public:
auto hello() const { return name.buf; }
};
int main()
{
Foo<6, "Hello!"> foo;
foo.hello();
}
I'm trying to add a template specialisation Foo<6, name> and it ends in this error:
macros.h: At global scope:
macros.h:3:18: error: class template argument deduction failed:
23 | class Foo<6, name>
| ^
macros.h:3:18: error: no matching function for call to ‘FixedString(FixedString<...auto...>)’
macros.h:7:15: note: candidate: ‘template<unsigned int N> FixedString(const char (&)[N])-> FixedString<N>’
7 | constexpr FixedString(const char (&s)[N])
| ^~~~~~~~~~~
macros.h:7:15: note: template argument deduction/substitution failed:
macros.h:13:18: note: mismatched types ‘const char [N]’ and ‘FixedString<...auto...>’
23 | class Foo<6, name>
| ^
macros.h:4:8: note: candidate: ‘template<unsigned int N> FixedString(FixedString<N>)-> FixedString<N>’
4 | struct FixedString
| ^~~~~~~~~~~
macros.h:4:8: note: template argument deduction/substitution failed:
macros.h:13:18: note: mismatched types ‘FixedString<N>’ and ‘FixedString<...auto...>’
23 | class Foo<6, name>
What is the proper way to specialise template classes with string template arguments?
g++ (Ubuntu 9.4.0-1ubuntu1~16.04) 9.4.0
What is the proper way to specialise template classes with string template arguments?
The given code is well-formed(in C++20) but fails to compile for gcc 10.2 and lower. It however compiles fine from gcc 10.3 and higher. Demo
Might be due to that not all C++20 features were fully implemented in gcc 10.2 and lower.
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.
How can we make a template accept only basic data types.
template <typename T>
void GetMaxValue( T& x )
{
//... Finds max Value
}
In the above function GetMaxValue we are able to pass any value without any an error.
But the std Function std::numeric_limits<T>::max() has handled it.
For example:
auto max = std::numeric_limits< std::map<int,int> >::max();
will Give an error error C2440: '<function-style-cast>' : cannot convert from 'int' to 'std::map<_Kty,_Ty>'
With constraints in C++20:
#include <type_traits>
template <class T>
requires std::is_arithmetic_v<T>
void GetMaxValue( T& x )
{
//... Finds max Value
}
Usage:
int a = 0;
GetMaxValue(a); // fine
std::vector<int> b;
GetMaxValue(b); // compiler error
Demo
With std::enable_if otherwise:
template <class T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
void GetMaxValue( T& x )
{
//... Finds max Value
}
Demo 2
The error messages pre-constraints are harder to read:
error: no matching function for call to 'GetMaxValue(std::vector<int>&)'
| GetMaxValue(b); // compiler error
| ^
Note: candidate: 'template<class T, typename std::enable_if<is_arithmetic_v<T>, int>::type <anonymous> > void GetMaxValue(T&)'
| void GetMaxValue( T& x )
| ^~~~~~~~~~~
note: template argument deduction/substitution failed:
error: no type named 'type' in 'struct std::enable_if<false, int>'
| template <class T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
| ^
In instantiation of 'void GetMaxValue(T&) [with T = int; typename std::enable_if<is_arithmetic_v<T>, int>::type <anonymous> = 0]'
vs
error: cannot call function 'void GetMaxValue(T&) [with T = std::vector<int>]'
| GetMaxValue(b); // compiler error
| ^
note: constraints not satisfied
In function 'void GetMaxValue(T&) [with T = std::vector<int>]':
required by the constraints of 'template<class T> requires is_arithmetic_v<T> void GetMaxValue(T&)'
note: the expression 'is_arithmetic_v<T>' evaluated to 'false'
| requires std::is_arithmetic_v<T>
| ~~~~~^~~~~~~~~~~~~~~~~~
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