Why Statements Cannot Appear at Namespace Scope

Why statements cannot appear at namespace scope?

The expression p++ which you've written is at namespace scope. It is forbidden by the grammer of namespace-body which is defined in §7.3.1/1 as:

namespace-body:

     declaration-seqopt

which says the namespace-body can optionally contain only declaration. And p++ is surely not a declaration, it is an expression, therefore the Standard implicitly forbids it. The Standard might have explicit statement forbidding this, but I think the above should be enough.

In the same way, you cannot do this:

namespace sample
{
f(10,10); //error
std::cout << "hello world" << std::endl;//error
}

But if you somewhow convert expressions into declarations (or rather use expressions in declarations), then you could evaluate the so-called expressions. Here is one trick:

#include<iostream>

namespace sample
{
struct any { template<typename T> any(const T&){} };

void f(int a,int b) { std::cout << a * b << std::endl; }

any a1= (f(10,10), 0); //ok
any a2 = std::cout << "hello world" << std::endl;//ok
}

int main() {}

Output (if you're lucky):

100
hello world

Online demo : http://ideone.com/icbhh

Notice that the return type of f() is void, which means I cannot write the following (see error):

any a1 = f(10,10); //error

That is why I used comma operator so that the expression could have some value, which evaluates to the last operand in the comma expression. In case of std:cout, since it returns std::ostream&, I don't need to use comma operator; it is fine without it.

One more interesting thing in the above code: why I defined any and a templated constructor in it? The answer is, I wrote this so that I could assign value of any type (no pun intended), be it int, std::ostream& or whatever. The templated constructor can take argument of any type.

But don't write such code. They're not guaranteed to work the way you expect.

Read the answers in this topic where you would see why such coding could be dangerous:

  • Is main() really start of a C++ program?

Why block scope at global namespace is not allowed?

I am curious as to why creating a block scope {} outside any function (in global scope) is not permitted.

It would be pointless and misleading. Variables declared outside any function are statically allocated so never go out of scope (except at the end of the program).


Edit: to make a variable exist transiently on program startup, you can do something like:

static auto throwaway_name = [] () { MyClass myVar; return 0; } ();

The only thing this allocates statically is an int (which might get optimised out, I'm not sure).

Why can't I declare a concept at class scope?

The fundamental difficulty that would arise is that concepts could become dependent:

template<class T>
struct A {
template<T::Q X>
void f();
};

Is X a non-type template parameter of (dependent) type T::Q (which does not require typename in C++20), or is it a type template parameter constrained by the concept T::Q?

The rule is that it’s the former; we would need new syntax (along the lines of typename/template) to express the other possibility: perhaps something like

template<T::concept Q X> requires T::concept R<X*>
void A::g() {}

No one has explored such an extension seriously, and it could easily conflict with other extensions to concept syntax that might be more valuable.

Using variables defined in an anonymous namespace in another namespace

CListName = "ListName"; is a statement (specifically, it's an assignment expression, which is an expression statement).

A statement cannot appear at namespace scope; you need to put the statement into a function.

a template declaration cannot appear at block scope (template class in main)

Since u didn't write a constructor for A, I supposed u want to use the inherited one, hence u have to provide the following line in A

using List<T>::List;

And since u used c++11, u have to provide the template arg, as follows

A<int> a(10);

If u want to make the compiler figure it out, use c++17 or c++20 and provide the following guide

template<class T> A(T)-> A<T>;

Now the full code with c++17 will be

template<typename T>
class List
{
public:
List(T) {}
};
template<typename T>
class A: public List<T>
{
public:
using List<T>::List;
};
template<class T> A(T)-> A<T>;
int main()
{ //No problem here...!
A a(10);
}

And with c++11 will be

template<typename T>
class List
{
public:
List(T) {}
};
template<typename T>
class A: public List<T>
{
public:
using List<T>::List;
};

int main()
{ //No problem here...!
A<int> a(10);
}

template declaration cannot appear at block scope

In your

template <class T>
SimpleVector<T>::SimpleVector(int s)

there is a mismatch of opening and closing braces for the for loop at the last.

And in the destructor, you should clear the vector as aptr->clear();, because aptr is a pointer variable.



Related Topics



Leave a reply



Submit