I've been trying to define a class method which uses a return type declared in the class namespace:
template<class T, int SIZE>
class SomeList{
public:
class SomeListIterator{
//...
};
using iterator = SomeListIterator;
iterator begin() const;
};
template<class T, int SIZE>
iterator SomeList<T,SIZE>::begin() const {
//...
}
When I try to compile the code, I'm getting this error:
Building file: ../SomeList.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"SomeList.d" -MT"SomeList.d" -o "SomeList.o" "../SomeList.cpp"
../SomeList.cpp:17:1: error: ‘iterator’ does not name a type
iterator SomeList<T,SIZE>::begin() const {
^
make: *** [SomeList.o] Error 1
I Also tried to define the method like this:
template<class T, int SIZE>
SomeList::iterator SomeList<T,SIZE>::begin() const {
//...
}
And this:
template<class T, int SIZE>
SomeList<T,SIZE>::iterator SomeList<T,SIZE>::begin() const {
//...
}
Result:
Building file: ../SomeList.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"SomeList.d" -MT"SomeList.d" -o "SomeList.o" "../SomeList.cpp"
../SomeList.cpp:17:1: error: invalid use of template-name ‘SomeList’ without an argument list
SomeList::iterator SomeList<T,SIZE>::begin() const {
^
make: *** [SomeList.o] Error 1
What am I doing wrong?
The name iterator is scoped to your class and it is a dependent name. In order to use it you need to use the scope operator and the typename keyword
typename SomeList<T,SIZE>::iterator SomeList<T,SIZE>::begin() const
Live Example
As pointed out in the comment by M.M you can also use the trailing return syntax as
auto SomeList<T,SIZE>::begin() const -> iterator {
Live Example
Related
When compiling this code, I get an error:
#include <cstdio>
template<size_t Index, typename T, size_t Length>
T& get(T (&arr)[Length]) {
static_assert(Index < Length, "Index out of bounds");
return arr[Index];
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int value = get<5>(arr);
printf("value = %d\n", value);
}
Error message:
In function 'T& get(T (&)[Length])':
Line 5: error: there are no arguments to 'static_assert' that depend on a template parameter, so
a declaration of 'static_assert' must be available
compilation terminated due to -Wfatal-errors.
Can someone explain how to fix this please?
Running with gcc 4.1.2
flags:
-O -std=c++98 -pedantic-errors -Wfatal-errors -Werror -Wall -Wextra -Wno-missing-field-initializers -Wwrite-strings -Wno-deprecated -Wno-unused -Wno-non-virtual-dtor -Wno-variadic-macros -fmessage-length=0 -ftemplate-depth-128 -fno-merge-constants -fno-nonansi-builtins -fno-gnu-keywords -fno-elide-constructors -fstrict-aliasing -fstack-protector-all -Winvalid-pch
This language feature became available in C++ only with C++11, see:
https://en.cppreference.com/w/cpp/language/static_assert
I'm trying to compile the EnTT library (version 2.7.3 for cpp14) using MinGW GCC-6.3.0 in Eclipse Oxygen. When compiling, I get these errors:
Info: Internal Builder is used for build
g++ -std=c++1y -D__GXX_EXPERIMENTAL_CXX0X__ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++14 -o "source\\main.o" "..\\source\\main.cpp"
In file included from c:\mingw\include\entt\entt.hpp:10:0,
from ..\source\includes.hpp:23,
from ..\source\main.cpp:1:
c:\mingw\include\entt\entity/helper.hpp: In function 'void entt::connect(entt::Sink<void(entt::Registry<Entity>&, Entity)>)':
c:\mingw\include\entt\entity/helper.hpp:56:19: error: parse error in template argument list
sink.template connect<dependency<Entity, Dependency...>>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c:\mingw\include\entt\entity/helper.hpp:56:19: error: expected identifier
c:\mingw\include\entt\entity/helper.hpp: In function 'void entt::disconnect(entt::Sink<void(entt::Registry<Entity>&, Entity)>)':
c:\mingw\include\entt\entity/helper.hpp:79:19: error: parse error in template argument list
sink.template disconnect<dependency<Entity, Dependency...>>();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c:\mingw\include\entt\entity/helper.hpp:79:19: error: expected identifier
Here are the truculent functions in question:
template<typename Entity, typename... Component>
void dependency(Registry<Entity> ®istry, const Entity entity) {
using accumulator_type = int[];
accumulator_type accumulator = { ((registry.template has<Component>(entity) ? void() : (registry.template assign<Component>(entity), void())), 0)... };
(void)accumulator;
}
template<typename... Dependency, typename Entity>
inline void connect(Sink<void(Registry<Entity> &, const Entity)> sink) {
sink.template connect<dependency<Entity, Dependency...>>();
}
template<typename... Dependency, typename Entity>
inline void disconnect(Sink<void(Registry<Entity> &, const Entity)> sink) {
sink.template disconnect<dependency<Entity, Dependency...>>();
}
I am trying to have a const string reference as non-type template argument , i am not able to get past this compilation error .
test.h :
#include <string.h>
#include <iostream>
template<const std::string& V> class TestTmplt
{
};
const std::string& TEST_REF = "TESTREF" ;
typedef TestTmplt<TEST_REF> TestRefData ;
test.cpp :
#include <test.h>
template class TestTmplt<TEST_REF> ;
Compilation error :
./test.h:10:34: error: could not convert template argument âTEST_REFâ to âconst string& {aka const std::basic_string<char>&}â
./test.h:10:49: error: invalid type in declaration before â;â token
I am compiling on centos linux , using following gcc command
g++ -c -MMD -MF test.u -g -D_LINUX -std=c++03 -pthread -Wall -DVALGRIND -Wno-missing-field-initializers -z muldefs -I. -o test.o test.cpp
The problem is that TEST_REF is not of type std::string, but of type const std::string &, i.e. it's not an object of type std::string and so cannot be used as the template argument. With a slight change, it works:
#include <string>
template<const std::string& V> class TestTmplt
{
};
std::string TEST_REF = "TESTREF";
template class TestTmplt<TEST_REF>;
[Live example]
I have two different approaches to a templated function using auto and decltype but one of them does not compile, yielding two error:
Where is the main difference between the following versions of the code:
This compiles
template<typename MemoryMapper, typename EngineParts>
class EngineBase {
const MemoryMapper memoryMapper;
public:
const EngineParts engineParts;
EngineBase();
virtual ~EngineBase();
template<typename Mapper, typename MemoryAccessor>
void getMemoryManager(void);
template<MemoryMapper,typename MemoryAccessor>
auto getMemoryManager(void)->decltype(memoryMapper.getMemoryManager<MemoryAccessor>())
{
return memoryMapper.getMemoryManager<MemoryAccessor>();
}
};
While this does not
template<typename MemoryMapper, typename EngineParts>
class EngineBase {
const MemoryMapper memoryMapper;
public:
const EngineParts engineParts;
EngineBase();
virtual ~EngineBase();
template<typename MemoryAccessor>
auto getMemoryManager(void)->decltype(memoryMapper.getMemoryManager<MemoryAccessor>())
{
return memoryMapper.getMemoryManager<MemoryAccessor>();
}
};
The error output is as follows:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -o EngineBase.o "..\\EngineBase.cpp"
In file included from ..\EngineBase.cpp:7:0:
..\EngineBase.h:22:84: error: expected primary-expression before '>' token
auto getMemoryManager(void)->decltype(memoryMapper.getMemoryManager<MemoryAccessor>())
^
..\EngineBase.h:22:86: error: expected primary-expression before ')' token
auto getMemoryManager(void)->decltype(memoryMapper.getMemoryManager<MemoryAccessor>())
^
14:50:52 Build Finished (took 2s.587ms)
Since I don't want to specifically write the first template argument on every use and it would create the impression that there are more functions defined than realistically are, how can I get the second version to work without introducing another template argument? Function parameters would be ok, though.
template<typename MemoryAccessor>
auto getMemoryManager(void)->decltype(memoryMapper.template getMemoryManager<MemoryAccessor>())
// ~~~~~~~^
{
return memoryMapper.template getMemoryManager<MemoryAccessor>();
// ~~~~~~~^
}
In the following code, it would appear that g++ 4.7.2 gets confused by a using based type alias.
The code:
#include <map>
enum class Direction
{
UP=-1,
DOWN=1
};
template <Direction dir>
struct Comparator
{
bool operator()(int lhs, int rhs) const
{
return lhs<rhs; // Comparison should be based on dir
// but let's not even use dir for now
}
};
template <Direction dir>
using IntToIntMap=std::map<int, int, Comparator<dir>>;
template <Direction dir>
void TestFunc()
{
using TheMap=IntToIntMap<dir>; // TheMap should be a synonym for
// IntToIntMap<dir>
typename IntToIntMap<dir>::value_type value1; // This compiles
typename TheMap::value_type value2; // This does not (???)
}
int main()
{
TestFunc<Direction::UP>();
}
Compile the code with:
g++ -std=c++11 -Wall --pedantic -o test test.cpp
Unexpected compile time errors:
test.cpp: In instantiation of 'void TestFunc() [with Direction dir =
(Direction)-1]
test.cpp:34:29: required from here
test.cpp:29:33: error: no type named 'value_type' in 'using TheMap =
IntToIntMap<dir>'
What is wrong with the line in question? Is the code in violation of the the C++11 standard or is this a g++ 4.7.2 bug? Live code in g++-4.7
It's fixed in gcc-4.8, per the comments:
4.7: http://coliru.stacked-crooked.com/view?id=9d55db125baaac0b169e61bbcfcb2a26-f2a3752efd0426bdaa29babef505f76e
4.8: http://coliru.stacked-crooked.com/a/6cd0ad895d067e51